User abend

U4087: Language Environment recursive error

A U4087 abend means Language Environment hit a new error while it was still handling an earlier one, and the nesting went past the limit set by the DEPTHCONDLMT runtime option. The first error, not the last, is the one to fix.

Other names for this code

Also written as U4087, abend U4087, user abend 4087, 4087 abend, S000 U4087, LE abend 4087, ABEND=S000 U4087, recursive error 4087.

What it means

This page covers user abend 4087 as issued by z/OS Language Environment (LE), the runtime for COBOL, PL/I and C. User abend numbers belong to the product that issues them. When a program runs under LE in IMS, CICS or batch, a U4087 next to CEE messages is this code.

LE calls any error a condition. While LE handles a condition, it runs its own code, any handler the program registered, and the code that writes messages. If one of those raises a new condition, the new one is nested inside the first. The DEPTHCONDLMT runtime option caps how deep that nesting may go. When the cap is passed, LE stops trying and ends the program with U4087.

The reason code tells you which part of LE was active when the nested error came. Reason code 7, for example, means a new condition arrived while LE was writing a message. Look up other values under abend 4087 in the LE runtime messages manual for your release.

In practice, U4087 often follows damaged storage. The first error happens, LE tries to handle it, and the same damage trips it up again.

Common causes

  • A storage overlay. The program wrote past a table or buffer, or through a bad pointer, and damaged storage that LE uses while handling errors. A GETMAIN or allocation shorter than the record copied into it is a common way this happens.
  • A condition handler that fails itself. That could be a routine registered with CEEHDLR or a PL/I ON-unit with a bug in it.
  • A second error while LE writes the message for the first one, shown by reason code 7.
  • A program designed to handle conditions inside conditions, run with a DEPTHCONDLMT value too low for it. This one is rare.

How to find the problem

  1. Note the reason code from IEF450I or the symptom dump.
  2. Read the LE messages in the step's output from the top. The earliest CEE, IGZ, IBM or EDC message with severity E, S or C is the first error. Later messages often describe side effects.
  3. Don't expect a complete CEEDUMP. LE may not have managed to write one, or it may stop partway.
  4. Rerun with the runtime options TERMTHDACT(UAIMM) and TRAP(ON,NOSPIE). LE then lets the system take a dump at the moment of the first error, before any recursion. Use these for problem diagnosis only.
  5. Rerun with RPTOPTS(ON) to see the DEPTHCONDLMT value in effect and where it was set.

How to fix it

  • Fix the first error. Once it is gone, there is nothing for LE to recurse on.
  • If storage is being overlaid, find the code doing it. Compile COBOL with SSRANGE in test, and check that every area the program gets is at least as long as the data moved into it.
  • Fix or remove a condition handler that raises errors of its own.
  • Raise DEPTHCONDLMT only when the program is designed to nest conditions. For most programs a higher value just delays the same abend.

What it looks like

IEF450I CLMPRC01 STEP020 - ABEND=S000 U4087 REASON=00000007

IBM documentation

IBM Language Environment documentation. Use the documentation for your installed release.

This link opens the relevant IBM reference library or lookup instructions. Match the complete code and your installed product release; it is not a code-specific review.

Report a correction to WND Software.

Questions

Will a higher DEPTHCONDLMT fix U4087?

Usually not. The nesting comes from a real error that keeps causing more errors, so the fix is to find and correct the first one.

Why is there no useful dump?

By the time LE gives up, the first error is several layers back and storage may be damaged. TERMTHDACT(UAIMM) with TRAP(ON,NOSPIE) gets a dump at the first error instead.

I got U4087 in an IMS region. Is it an IMS abend?

Not if the messages before it come from LE, such as CEE or IGZ messages. IMS has its own user abend codes, and the IMS messages would name the IMS code.