PL/I ZERODIVIDE (ONCODE 320) and CONVERSION (ONCODE 6xx)
A PL/I program raised a condition it did not handle. ONCODE tells you which one and why; an ON-unit lets you handle it instead of failing.
What happened
A PL/I program hit a run-time condition — a division by zero, or character data that could not be converted to a number. With no ON-unit for it, the implicit action applied: a run-time message was issued and the ERROR condition was raised, which normally ends the program under Language Environment.
MPCALC01 CONDITION TRAPPED: ZERODIVIDE ONCODE=320 MPCALC01 ACCOUNT=00012345 UNITS=0 - RECORD REJECTED MPLOAD02 CONVERSION ERROR ONCODE=601 ONSOURCE='12A4' ONCHAR='A'
What it means
PL/I signals unusual events as named conditions. Each occurrence also has a numeric condition code, returned by the ONCODE built-in function inside an ON-unit (outside one it returns 0). IBM's Messages and Codes lists every code; two you will meet often:
- ZERODIVIDE, ONCODE 320 — the program divided by zero (IBM's description also covers a SIGNAL ZERODIVIDE statement).
- CONVERSION, codes in the 600s — a character value could not be converted, for example 601 for bad data found by GET LIST or GET DATA with the FILE option, or 602 for unknown source attributes after a TRANSMIT condition.
ZERODIVIDE and CONVERSION are enabled by default, as are FIXEDOVERFLOW, OVERFLOW and INVALIDOP. SIZE, STRINGRANGE, STRINGSIZE and SUBSCRIPTRANGE are disabled by default and must be enabled with a condition prefix such as (SUBSCRIPTRANGE):.
Typical causes
- A divisor read from data that can be zero — quantity, rate, count of items.
- Numeric fields containing spaces, letters or a decimal point where none is expected.
- A record layout that does not match the file, so numeric fields are read from the wrong positions.
- Uninitialised variables used in arithmetic.
Symptoms
- A run-time message with the ONCODE and the condition name, followed by the step ending.
- When ERROR is raised by the implicit action of another condition, the message for the original condition is the one to investigate.
- Failures that depend on the data, not on the code path.
Where to look
- The run-time messages in the job log or SYSPRINT, including the statement or offset given.
- The compile listing, to map the offset to a source statement.
- The input record being processed when the condition was raised — browse it in hex.
- A CEEDUMP if one was produced.
How to diagnose
- Note the condition name and the ONCODE.
- Find the statement from the message and the compile listing.
- For ZERODIVIDE, identify the divisor and where its value came from.
- For CONVERSION, use the ONSOURCE (whole field) and ONCHAR (failing character) values to see exactly what was rejected.
How to fix
Test the divisor before dividing, and decide with the business what a zero should mean. For conversions, validate input before using it as a number. Where the program must survive bad data, code an ON-unit: ON ZERODIVIDE to log and skip, or ON CONVERSION using the ONSOURCE and ONCHAR pseudovariables to substitute a valid value and continue.
ON ZERODIVIDE BEGIN;
PUT SKIP LIST('ZERODIVIDE ONCODE=', ONCODE(), ' ACCT=', ACCT_NO);
REJECT_COUNT = REJECT_COUNT + 1;
GO TO NEXT_RECORD;
END;How to prevent
- Validate numeric input at the edge of the program.
- Enable SUBSCRIPTRANGE and STRINGRANGE in test builds to catch other silent errors.
- Do not disable conditions with prefixes like
(NOZERODIVIDE):to hide failures — IBM states that a disabled condition that occurs is a program error with unpredictable results.
Production considerations
Interview question
What is ONCODE and where can you use it?
Stuck on something else?
Ask the community or search the full course.