User abend

U4038: Language Environment severe error

A U4038 abend means Language Environment ended a COBOL, PL/I or C program because of a severe error that nothing handled. The real cause is in the messages LE wrote just before the abend, such as an IGZ or CEE message.

Also written as U4038, abend U4038, user abend 4038, 4038 abend, S000 U4038, LE abend 4038, ABEND=S000 U4038.

What it means

Language Environment (LE) is the runtime that COBOL, PL/I and C programs use on z/OS. It gives every runtime error a severity. When an error of severity 2 or higher happens and no handler deals with it, LE ends the program. If the ABTERMENC runtime option is ABEND, it does that with user abend 4038. If ABTERMENC is RETCODE, the step ends with a return code built from the severity instead, such as 3000.

U4038 is only the messenger. The actual error is described in the messages LE wrote before it. It typically appears for errors found by software, such as a COBOL runtime check or a file that wouldn't open. When the error began as a hardware program check, like a data exception, the job usually shows the original system code (S0C7, S0C4) instead of U4038.

Common causes

  • A file OPEN failed and the program has no FILE STATUS clause or error declarative. The COBOL runtime writes IGZ0035S with the file status, often 35 (no DD statement or no data set) or 39 (the record length or format doesn't match the file).
  • A subscript or index went out of range in a program compiled with SSRANGE. The runtime writes IGZ0006S.
  • Control ran off the end of a COBOL program that has no GOBACK, STOP RUN or EXIT PROGRAM at the end. The runtime writes IGZ0037S.
  • Another I/O error on a file without FILE STATUS checking.
  • A severe error in PL/I or C code, reported by messages that start with IBM or EDC.

How to find the problem

  1. Read the messages just before the abend. LE writes them to its message file, which is the SYSOUT DD unless your site changed the MSGFILE option. Messages starting with CEE come from LE itself, IGZ from the COBOL runtime, IBM from PL/I and EDC from C.
  2. Look for the message whose ID ends in E (error), S (severe) or C (critical). That is usually the error LE ended the program for. Warnings ending in W often come first and are not the cause.
  3. Check the CEEDUMP output if the step produced one. The TERMTHDACT runtime option controls how much LE writes there. Its traceback lists the active programs in calling order with the offset or statement where each one was.
  4. Turn an offset into a statement with the compile listing, or compile with the TEST option so the traceback shows statement numbers directly.

How to fix it

  • For IGZ0035S, correct the DD statement or create the missing data set, then rerun the step. Add FILE STATUS to every SELECT and check it after each OPEN, READ and WRITE.
  • For IGZ0006S, fix the table size or the logic that sets the subscript.
  • For IGZ0037S, end the program with GOBACK.
  • For any other message, look up its ID in the LE or compiler runtime messages for your release, and fix what it names.
  • The application team usually fixes U4038. When the message points at a missing data set or a JCL mistake, the people who run the batch schedule fix it.

What it looks like

IGZ0035S There was an unsuccessful OPEN or CLOSE of file CUSTIN in program PAYEXTR at relative location X'0452'.
         Neither FILE STATUS nor an ERROR declarative were specified. The status code was 35.
         From compile unit PAYEXTR at entry point PAYEXTR at compile unit offset +00000452
IEF450I PAYRUN01 STEP010 - ABEND=S000 U4038 REASON=00000001

Questions

Why did my job get S0C7 instead of U4038?

When the error starts as a hardware program check, LE usually ends the step with that original system code. U4038 is typical for errors that software detected, such as a failed OPEN or an out-of-range subscript.

Does U4038 mean something is wrong with Language Environment?

Almost never. LE is reporting an error in the program, its data or its JCL. The message just before the abend says which.

Why does the same error give return code 3000 in another job?

That job runs with the LE option ABTERMENC(RETCODE), so LE ends it with a return code instead of an abend. The messages and the fix are the same.