COBOL Troubleshooting
Input record layout mismatch
Troubleshooting guide for Input record layout mismatch. File handling bugs usually come from the FD or SELECT not matching the real dataset — the program opens fine and then misreads every record.
What it means
- COBOL file I/O is declarative: SELECT, FD, and the JCL DD statement must all agree on organization, record format, and length.
- When they disagree, the program rarely abends at OPEN — it reads shifted data or hits EOF at the wrong place.
- FILE STATUS is the only reliable signal; without it, I/O errors are invisible.
Common causes
- READ fails to detect EOF because the AT END clause is missing or the EOF flag is tested before the first READ.
- OPEN EXTEND on a sequential file positions at end-of-file — a subsequent READ hits immediate EOF, which looks like an empty file.
- CLOSE fails with file status 30/90+ because a previous WRITE had an unhandled error, or the DD was DUMMY.
- FD RECORDING MODE / BLOCK CONTAINS disagrees with the real DCB — records arrive shifted or truncated.
- Input record layout (copybook) is shorter than the real LRECL, so trailing fields land in the wrong positions.
- Output fields shifted: numeric-edited or alphanumeric MOVEs into wrong offsets after a layout change.
- Record count mismatch: header/trailer records counted as data, or a restart reprocessed part of the file.
- Duplicate output: program writes the same record twice because the WRITE is inside a loop that also handles the AT END path.
How to diagnose
- Always code FILE STATUS and DISPLAY it after OPEN/READ/WRITE/CLOSE during diagnosis — status 00 means success, anything else names the problem.
- Compare FD record length against the dataset LRECL (check with ISPF 3.4 or LISTCAT) — they must match for fixed files.
- For shifted fields: DISPLAY the first input record in hex and map each field offset against the copybook.
- For EOF problems: verify the AT END clause exists on every READ and the EOF flag is initialized to "N" before the loop.
- Check the JCL DD: DISP, DSN, and DCB on the DD can override what the program expects.
How to fix it
- Add FILE STATUS to every SELECT and check it after each I/O verb; abend the step with a clear message on unexpected status.
- Correct the FD/copybook to match the real LRECL, or fix the JCL DCB — one side must change so both agree.
- For OPEN EXTEND followed by reads: CLOSE and re-OPEN INPUT, or use a separate SELECT for the read pass.
- Move the WRITE out of the AT END handling path so the last record is written exactly once.
- Count input records, output records, and rejects separately, and balance them in the trailer.
Example: FILE STATUS checked after every I/O verb
SELECT INPUT-FILE ASSIGN TO INFILE
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FS-IN.
*
OPEN INPUT INPUT-FILE.
IF WS-FS-IN NOT = "00"
DISPLAY "OPEN FAILED, FS=" WS-FS-IN
MOVE 16 TO RETURN-CODE
GOBACK
END-IF.
READ INPUT-FILE
AT END MOVE "Y" TO EOF-FLAG
NOT AT END ADD 1 TO WS-IN-COUNT
END-READ.
FILE STATUS "00" means success; any other value after OPEN/READ tells you exactly what went wrong.
Interview tip
- Q: A job reads a file and processes zero records, but the file is not empty. What do you check?
- A: First the FILE STATUS after OPEN — 35 means the dataset was not found, 39 means the FD and DCB disagree. Then I check whether the program opened the file EXTEND (which positions at EOF) and whether the AT END flag was initialized before the first READ.
Prevention checklist
- Code FILE STATUS on every file and check it after every OPEN, READ, WRITE, and CLOSE.
- Keep one copybook per layout shared by all programs reading the file.
- Balance record counts (in = out + rejects) and abend the step on mismatch.
- Test with empty files, one-record files, and files with bad trailing records.
