In COBOL, every file I/O operation can succeed, hit a normal condition (like end of file), or fail. The FILE STATUS clause lets you capture a two-character status code after each operation so your program can react correctly. This page explains how to declare and use file status, what the two bytes mean, and how to handle the most common codes for sequential and keyed files.
When you ask the computer to read or write a file, it can say "done," "there is nothing more to read," or "something went wrong." File status is that answer in the form of two letters or digits. Your program looks at those two characters and decides: keep going, stop reading, or show an error. So file status is just the program's way of knowing what happened after each file operation.
You associate a file with a status data item in the SELECT statement using the FILE STATUS clause. The status item must be exactly two bytes—typically PIC X(2) or PIC XX. It can be in WORKING-STORAGE or in a place that is accessible when the file is used. The runtime sets this item after every OPEN, CLOSE, READ, WRITE, REWRITE, DELETE, and START for that file. You should check it after each I/O to drive your logic.
12345678910111213141516171819202122WORKING-STORAGE SECTION. 01 WS-INPUT-STATUS PIC X(2). 01 WS-OUTPUT-STATUS PIC X(2). FD INPUT-FILE. 01 INPUT-RECORD PIC X(80). FD OUTPUT-FILE. 01 OUTPUT-RECORD PIC X(80). PROCEDURE DIVISION. OPEN-FILES. OPEN INPUT INPUT-FILE IF WS-INPUT-STATUS NOT = '00' DISPLAY 'Open input failed: ' WS-INPUT-STATUS STOP RUN END-IF OPEN OUTPUT OUTPUT-FILE IF WS-OUTPUT-STATUS NOT = '00' DISPLAY 'Open output failed: ' WS-OUTPUT-STATUS STOP RUN END-IF.
In the SELECT (in ENVIRONMENT DIVISION), you would have something like SELECT INPUT-FILE ASSIGN TO ... FILE STATUS WS-INPUT-STATUS. The exact syntax depends on your compiler; the important part is that each file has its own status item and you check it after every I/O.
The file status is two characters. The first character is the category; the second adds detail. So you can test the first byte to decide the kind of condition (success, at end, invalid key, permanent error, etc.) and optionally the full two bytes for specific handling. For example, 00 is success, 10 is end-of-file, 23 is record not found (invalid key), 30 is permanent error.
| First byte | Category | Meaning | Typical action |
|---|---|---|---|
| 0x | Success | Operation completed successfully. Second byte gives detail (00 = normal success). | Continue processing. |
| 1x | AT END | Sequential read reached end of file or optional file not present. | Exit read loop; handle EOF. |
| 2x | Invalid key | Keyed operation failed: duplicate key, record not found, or sequence error. | Check key and logic; handle duplicate or missing record. |
| 3x | Permanent error | Serious I/O or system error (e.g. disk failure, file not found at OPEN). | Do not retry same op; log and recover or abend. |
| 4x | Logic error | Programmer or logic error (e.g. wrong OPEN mode, invalid request). | Fix program logic. |
| 9x | Implementer / runtime | COBOL runtime or implementer-defined error. | Check documentation; possible bug or environment issue. |
Comparing the full two-byte value (e.g. IF WS-STATUS = '10') is reliable. Comparing only the first byte (e.g. WS-STATUS(1:1) or a reference-modified substring) lets you handle all "invalid key" codes (2x) together if you do not need to distinguish 21, 22, 23, etc.
Exact codes can vary by compiler and file type (sequential, VSAM, etc.). The following are widely used. Always check your compiler and runtime documentation for the full list and for your environment.
| Code | Meaning | When it occurs |
|---|---|---|
| 00 | Success. | Any I/O completed normally. |
| 02 | Duplicate key (optional). | WRITE or READ on keyed file; duplicate key detected; optional key clause may allow continuation. |
| 04 | Invalid record length. | Fixed-length record file: record size does not match. |
| 05 | Optional file not present. | OPEN on optional file; file did not exist (often treated like empty). |
| 10 | End of file. | Sequential READ when no next record exists. |
| 21 | Sequence error. | Sequential file: key out of order (e.g. ascending key violated). |
| 23 | Record not found. | READ by key, REWRITE, DELETE, or READ after START; no matching record. |
| 30 | Permanent error. | System-level I/O failure (e.g. disk error, file not found for required file). |
| 35 | File not found at OPEN. | Non-optional file was not present at OPEN (e.g. missing dataset). |
Code 00 is the only "all good" for normal continuation. Code 10 is normal for sequential files when you have read all records. Codes 23 and 30 are common for keyed and error handling: 23 for "record not found" or invalid key, 30 for serious I/O failure. Codes 05 and 35 relate to optional vs required files at OPEN: 05 often means optional file not present (acceptable); 35 means a required file was missing (error).
After OPEN, check that the status is 00 (or 05 for optional input if you allow it). After each READ, check for 00 (success), 10 (end of file for sequential), or an error code (e.g. 23, 30). After WRITE, REWRITE, DELETE, or START, check for 00 or the appropriate invalid-key or error code. After CLOSE, you can check for 00 to confirm no error. Many programs use EVALUATE WS-STATUS or a series of IF/ELSE to branch on the status and then PERFORM different paragraphs (e.g. EOF-PARAGRAPH, INVALID-KEY-PARAGRAPH, ERROR-PARAGRAPH).
123456789READ-INPUT. READ INPUT-FILE AT END SET WS-EOF TO TRUE NOT AT END PERFORM PROCESS-RECORD END-READ IF WS-INPUT-STATUS NOT = '00' AND WS-INPUT-STATUS NOT = '10' DISPLAY 'Read error: ' WS-INPUT-STATUS PERFORM ABEND-ROUTINE END-IF.
Using AT END and NOT AT END is one way to handle 10 vs 00. The FILE STATUS is still set, so you can also rely on it alone: IF WS-INPUT-STATUS = '10' perform end-of-file logic, else if '00' process the record, else handle error. For keyed files, INVALID KEY and NOT INVALID KEY (or FILE STATUS 2x) drive the logic when the key is missing or duplicate.
For sequential files, the codes you will see most are 00 (success), 10 (end of file), and sometimes 21 (sequence error if keys are out of order). For keyed files (e.g. VSAM KSDS), 00, 10, 23 (record not found), and 30 are common; 02 can appear for duplicate keys if the file allows it and you use the optional duplicate-key clause. OPEN failures (e.g. 35 for required file not found, 30 for other permanent errors) apply to both. The FILE STATUS clause works the same; only the set of possible codes and their meanings differ by file type.
1. After a READ, you should check FILE STATUS to:
2. File status 10 means:
3. The first byte of a two-byte file status indicates: