How can we help you?

We have hundreds of highly-qualified, experienced experts working in 70+ technologies.

IBM i e-Book

A Developer’s Guide to Mastering IBM i Concepts

Report Program Generator (RPG)

Error Handling

Introduction

Exception handling in the AS400 system involves the process of gracefully managing and recovering from errors, exceptions, or abnormal conditions that may arise during program execution or system operations. It plays a critical role in ensuring the reliability, robustness, and integrity of applications running on the AS400.

RPG Exception Handling

RPG classifies exceptions into two main categories:

  • Program Exception: Some examples of program exceptions are division by zero, array index out-of-bounds, SQRT of a negative number, invalid date, time, or timestamp value.
  • File Exception: Some examples of file exceptions are undefined record type or a device error, record lock, update operation attempted without a prior read.
Status code

%STATUS code is a built-in function used to retrieve the status code of the most recent operation performed by operation codes within the program. This status code serves as an indicator of the success or failure of the operation. Typically, a status code of 0 signifies that the operation was completed successfully, while non-zero values indicate various types of error or exceptional conditions encountered during the operation.

The error is identified by a five-digit status code provided by %STATUS. Program status codes go between 00100 and 00999, whereas file status codes fall between 01000 and 01999. When a status code falls between 00000 and 00050, it is regarded as normal; that is, it is not caused by an exception or error situation.

There are different ways to indicate that RPG should handle an exception.

  • (a) Using error IndicatorIf the calculation specification has an error indicator for an operation and an exception is expected for that operation:
    • The indicator is set on.
    • The exception is handled.
    • Control resumes with the next RPG operation.

    Sample code:

    FEMPMASTER UF A E             DISK    USROPN
    
    C         5            SETLL         EMPR       33
    C                      EXSR           INDERRSR
    C                      EVAL           EMPNAME = 'ALEXA'
    C                      UPDATE     EMPR       33
    C                      EXSR           INDERRSR
    C                      SETON              LR
    
    C     INDERRSR      BEGSR
    C                       IF                  *IN33 = *ON
    C                       IF                  %STATUS(EMPMASTER) = 1211
    C                       OPEN           EMPMASTER
    C                       ELSEIF         %STATUS(EMPMASTER) = 1221
    C                       READ(E)      EMPMASTER
    C                       EVAL             EMPNAME = 'ALEXA'
    C                       UPDATE(E) EMPR
    C                       ENDIF
    C                       ENDIF
    C                       ENDSR
    

    (b) Using Operator Extender (E)

    If an ‘E’ operation code extender is included in the calculation specification and no error indicator is present, the error will be managed by this operator extender.

    %STATUS and %ERROR, two built-in functions, will be used to handle the error.


    Sample Code:

    Dcl-F EmpMaster Usage(*Input:*Update:*Output) UsrOpn;
    
    Setll(E) 5 EmpR;
    Exsr ErrSr;
    EmpName = 'ABC';
    Update(E) EmpR;
    Exsr ErrSr;
    *Inlr = *On;
    
    Begsr ErrSr;
    
    If %Error();
    If %Status(EmpMaster) = 1211;
    Open EmpMaster;
    Elseif %Status(EmpMaster) = 1221;
    Read(E) EmpMaster;
    EmpName = 'ABC';
    Update(E) EmpR;
    Endif;
    Endif;
    
    Endsr;
    
  • Using Monitor BlockA MONITOR group performs conditional error handling based on the status code. It consists of:
    1. A Monitor Block
    2. Zero or more ON-ERROR blocks
    3. An ENDMON statement

    Control moves on to the following statement after the MONITOR statement. The statements from the MONITOR statement to the first ON-ERROR statement make up the monitor block. Control is transferred to the relevant ON-ERROR block if an error arises during the processing of the monitor block.

    If all the statements in the MONITOR block execute successfully without errors, control proceeds to the statement following the ENDMON.

    Anywhere in the calculations, the monitor group can be provided. Within IF, DO, SELECT, or other monitor groups, it can be nested. Within monitor groups, the IF, DO, and SELECT groups can be nested.

    Level indicators can be used on the MONITOR operation, to indicate that the MONITOR group is part of total calculations.

    On the MONITOR statement, conditioning indicators are applicable. If they are not satisfied, control passes immediately to the statement following the ENDMON statement of the monitor group. Conditioning indicators cannot be used on ON-ERROR operations individually.

    When a subprocedure called from a MONITOR block encounters an error, the subprocedure ‘s error handling will take precedence. For instance, the *PSSR subroutine within the sub procedure will be called. Only if the sub procedure is unable to handle the error and the call fails with the error-in-call status of 00202 will the MONITOR group containing the call be taken into consideration.

    Errors that arise in a subroutine that is called from an EXSR statement within the monitor group are handled by the monitor group. The subroutine’s monitor groups take precedence if it has any.

    Branching operations are not allowed within a MONITOR block but are allowed within an ON-ERROR block.

    A monitor block’s LEAVE or ITER operations are applicable to all active DO groups that include the monitor block. For every subroutine, sub procedure, or procedure that contains a monitor block, the LEAVESR or RETURN operation is applicable.

    A few examples are given below. The first involves figuring out how to capture a “divide by zero” error with the program status code 00102:

    Sample Code:

    Dcl-S Num1   Zoned(2:0);
    Dcl-S Num2   Zoned(2:0);
    Dcl-S Result Zoned(5:0);
    Dcl-S Error  Char(50);
    
    Num1 = 10;
    
    Monitor;
    Result = Num1/Num2;
    On-Error 102;
    Result = 0;
    Error = 'Divide by 0';
    EndMon;
    
                        *Inlr = *On;
    

    Example2:

    Sample Code:

    Dcl-F EmpMaster Usage(*Input);
    Dcl-S Error Char(20);
    
    Monitor;
    Open EmpMaster;
    On-Error *File;
    Error = 'File Not Opened';
    EndMon;
    
    *Inlr = *On;
    
  • Using an Error Subroutine(a) Using a File Error (INFSR) Subroutine.To handle a file error or exception, you can write a file error (INFSR) subroutine. When a file exception occurs:
    • The INFDS is updated.
    • A file error subroutine (INFSR) receives control if the exception occurs:

    A file error subroutine can handle errors in more than one file.

    The following restrictions apply:

    • If an error occurs that is not related to the operation (for example, an array-index error on a CHAIN operation), then any INFSR error subroutine would be ignored. The error would be treated like any other program error.
    • Control passes to the RPG default exception handler rather than the error subroutine handler if a file exception arises at the beginning or end of a program (for instance, on an implicit open at the beginning of the cycle). As such, there will be no processing of the file error subroutine.
    • Errors in a global file used by a sub procedure cannot be handled by an INFSR.

    Take the following actions to include a file error subroutine in your program:

    • On a File Description specification, type the subroutine’s name after the keyword INFSR. The program error subroutine may be assigned control over the exception on this file if the subroutine name is *PSSR.
    • You can use the keyword INFDS to optionally identify the file information data structure on a File Description specification.
    • Enter a BEGSR operation in which the subroutine name specified for the keyword INFSR appears in the Factor 1 entry.
    • Determine whether there is a return point and code it on the subroutine’s ENDSR operation.
    • Code the rest of the file error subroutine. While any of the ILE RPG compiler operations can be used in the file error subroutine, it is not recommended that you use I/O operations to the same file that got the error. The ENDSR operation must be the last specification for the file error subroutine.


    Sample Code:

    Dcl-F EmpMaster Usage(*Input:*Update:*Output) INFDS(INFDS) Keyed
    INFSR(InfoSr) Usropn;
    
    Dcl-Ds InfDs;
    File_Status *Status;
    End-Ds;
    
    Dcl-S ReturnCd Char(6);
    
    Setll 00002 EmpR;
    EmpName = 'ABC';
    Update EmpR;
    *Inlr = *On;
    
    Begsr InfoSr;
    If File_Status = 1211;
    Open EmpMaster;
    ReturnCd = '*GETIN';
    Elseif File_Status = 1221;
    Read(E) EmpMaster;
    Update(E) EmpR;
    ReturnCd = '*CANCL';
    Endif;
    Endsr ReturnCd;
    

    (b) Using a Program Error Subroutine.

    Program error subroutines (*PSSR) can be written to handle exceptions or program errors. When a program error occurs:

    • The program status data structure is updated.
    • If an indicator is not specified in positions 73 and 74 for the operation code, the error is handled, and control is transferred to the *PSSR.

    After a file error, you can explicitly move control to a program error subroutine by adding *PSSR to the File Description specifications after the keyword INFSR.

    For any procedure within the module, a *PSSR can be coded. Every *PSSR is specific to the coding procedure.

    To add a *PSSR error subroutine to your program, you do the following steps:

    • Optionally identify the program status data structure (PSDS) by specifying an S in position 23 of the definition specification.
    • Enter a BEGSR operation with a Factor 1 entry of *PSSR.
    • Identify a return point, if any, and code it on the ENDSR operation in the subroutine.
    • Code the rest of the program error subroutine. Any of the ILE RPG compiler operations can be used in the program error subroutine. The ENDSR operation must be the last specification for the program error subroutine.


    Sample Code:

    Dcl-S Num1 Zoned(2:0);
    Dcl-s Num2 Zoned(2:0);
    Dcl-S Result Zoned(5:0);
    Dcl-S Error Char(20);
    Dcl-S ReturnCd Char(6);
    
    Dcl-Ds PSDS1 psds;
    Pgm_Status *Status;
    End-Ds;
    
    Num1 = 10;
    
    Result = Num1/Num2;
    
    *Inlr = *On;
    
    Begsr *Pssr;
    If Pgm_Status = 00102;
    Error = 'Divide by zero';
    ReturnCd = ' ';
    Else;
    Error = 'Error with status code';
    ReturnCd = '*CANCL';
    Endif;
    Endsr ReturnCd;
    
  • Default exception Handler.The RPG default error handler is called if there is no error indicator, ‘E’ extender, or error subroutine coded and no active MONITOR group could handle the exception.Sample Code:
    Dcl-F EmpMaster Usage(*Input:*Update:*Output);
    
    Setll 5 EmpR;
    EmpName = 'ABC';
    Update EmpR;
    *Inlr = *On;
    

CL Program Exception Handling

Monitor Message (MONMSG)

The monitor message (MONMSG) command enables us to take corrective action for escape, status, and notification messages that are present in a CL program at run time.

The messages are sent to the program message queue for the conditions specified in the command. If condition exists, the CL command specified on the MONMSG command runs.

It doesn’t handle diagnostic messages, but we can receive those messages from the message queue to get additional information related to the error.

Types of monitor message

  • Escape MessageAn escape message alerts your program to an error that prompted the sender to terminate the program.
    You can terminate your program or take corrective action by monitoring for escape messages.
  • Status or Notify MessageAn abnormal condition that is not severe enough for the sender to terminate is reported to your program via status and notification messages. By monitoring for status or notify message, your program can detect this condition and not allow the function to continue.Two levels of MONMSG command:
    • Program levelIn the CL program, the MONMSG is defined right after the final declared command.
      It will detect all error escape messages present in the program, regardless of whether there are any command level MONMSGs or not.Sample code:

      PGM
      DCLF        FILE(EMPMASTER) OPNID(OPNID1)
      /*  Program Level MONMSG   */
      MONMSG      MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
      CHKOBJ      OBJ(*LIBL/EMPMASTER) OBJTYPE(*FILE) MBR(*FIRST)
      
      ERROR:
      SNDPGMMSG     MSG('Object not found in the *LIBL')
      ENDPGM
      
    • command level.Here the MONMSG command immediately follows a CL command. If there is any error at a particular CL statement and it satisfies the condition specified in MONMSG, then the error is caught with this MONMSG.Sample Code:
      PGM
      DCLF        FILE(EMPMASTER) OPNID(OPNID1)
      /* Command Level MONMSG   */
      
      CHKOBJ       OBJ(*LIBL/EMPMASTER) OBJTYPE(*FILE) MBR(*FIRST)
      MONMSG       MSGID(CPF9801) EXEC(GOTO CMDLBL(ERROR))
      
      READ:
      RCVF        OPNID(OPNID1)
      MONMSG      MSGID(CPF0864) EXEC(GOTO CMDLBL(END))
      GOTO        READ
      
      ERROR:
      SNDPGMMSG  MSG('Object not found in the *LIBL')
      END:
      ENDPGM
      

How can we help you?

We have hundreds of highly-qualified, experienced experts working in 70+ technologies.

share_iconShare
X

Awards and Certifications

company-logo
company-logo
company-logo
company-logo
company-logo
company-logo
company-logo
company-logo
company-logo
company-logo