IBM Support

Proper usage of error code parameter for APIs

Question & Answer


Question

How do I properly use the error code parameter for IBM i APIs?

Answer

Many APIs use one common Error Code structure. Here is the doc on the Error Code structure:  

Here is what the Error Code Structure looks like:
Error code paramaters


The most common mistake made when the error code parameter is used for IBM i APIs is failing to initialize the Bytes Provided field of the error code structure. Initializing this field tells the API how many characters the error code structure you are passing it is. If you don't initialize it, it is blanks, which are x'40404040' which converts to 1,077,952,576 bytes. If your error code structure is only 16 bytes, and the failure writes 200 characters to the error code structure, you have now overwritten 184 characters in storage (commonly called storage corruption). Those characters can be anything including your data, pointers, and so on. This failure can cause unexpected results including corrupted data in your program variables or corrupted pointers resulting in machine checks.

If you initialize your Bytes Provided to the wrong size, the same storage corruption can occur. It needs to be initialized to a value less than or equal to the size of your error code data structure.

It's worth noting that even if your existing code does not initialize the Bytes Provided, and it worked for years, it doesn't mean that your code is OK. You did not have problems for one of two reasons:

  1. Your API call was not getting errors. If it doesn't write any errors, it doesn't modify the error code parameter, so storage is not corrupted. If your API gets an error in the future, it might result in storage corruption.
  2. You corrupted storage all along, but you either did not notice the storage corruption, or the storage being corrupted is not significant. There is no guarantee that it continues to be insignificant. After an OS upgrade or apply of PTFs, problems can surface because of how the OS lays out storage changes, and suddenly the storage contains something significant and corruption causes failures.

It's also important to point out that the Bytes Provided and Bytes Available are listed as binary(4). This definition means they are 4 bytes long. In RPG, use either a 9B or 10i, or BINDEC(9) or INT(10) in free-form syntax. Sometimes people use a 4b thinking it is 4 bytes, but in reality, it is 2 bytes, and passing only 2 bytes can cause problems.

Following are some examples of correct error code use in an RPGLE program that calls the QLIRNMO API (which does a MOVOBJ). First, let's look at the parameter list for the API:


Paramaters for QLIRNMO APPI with Error Code highlighted

The examples do not be use the optional parameters as they are not needed to demonstrate how to use the error code.

Example 1:

This example passes only bytes provided, and initializes bytes provided to 0, which tells the API that exceptions are signaled (and sent to the job log) for this API call. Your program can monitor for errors in any way you chose. No exception ID is provided to the program.

     D RenameObj       PR                  ExtPgm('QLIRNMO')
     D  FromObj                      20
     D  FromType                     10
     D  ToObj                        20
     D  ReplaceObj                    1
     D  ErrorCode                     4

     D FromObj         S             20    inz('TESTOBJ   *CURLIB   ')
     D FromType        S             10    INZ('*PGM      ')
     D ToObj           S             20    inz('NEWOBJ    *CURLIB   ')
     D ReplaceObj      S              1    inz('1')
     D ErrorCode       DS
     D  BytesProvided                100 inz(0)

      /free
       RenameObj(FromObj : FromType : ToObj : ReplaceObj : ErrorCode);
       *inlr=*on;
      /end-free     

Example 2:

This example uses a Data Structure for the Error Code, and uses the size of the data structure to initialize the bytes provided. The API does not signal an exception, but instead gives the exception ID in the Error Code structure. Your program can then look at the exception ID and do what it wants with it. In this case, it is just displaying it. Notice that for Bytes Provided, is initialized with the %Size built in function so it is the correct size.

     D RenameObj       PR                  ExtPgm('QLIRNMO')


     D  FromObj                      20
     D  FromType                     10
     D  ToObj                        20
     D  ReplaceObj                    1
     D  ErrorCode                    16

     D FromObj         S             20    inz('TESTOBJ   *CURLIB   ')
     D FromType        S             10    INZ('*PGM      ')
     D ToObj           S             20    inz('NEWOBJ    *CURLIB   ')
     D ReplaceObj      S              1    inz('1')
     D ErrorCode       DS
     D  BytesProvided                100 inz(%size(ErrorCode))
     D  BytesAvail                    4
     D  ExceptionID                   7
     D  RESERVED                      1
      /free
       RenameObj(FromObj : FromType : ToObj : ReplaceObj : ErrorCode);
       dsply ExceptionID;
       *inlr=*on;
      /end-free 
Example 3:

This example provides not only the Exception ID but also the Exception Data (replacement text from the exception) to the program. The number of characters for the exception data depends on how much replacement text there is. I specified 256 characters, which are enough space for replacement text for most messages. If it is not enough, it is truncated.

     D RenameObj       PR                  ExtPgm('QLIRNMO')
     D  FromObj                      20
     D  FromType                     10
     D  ToObj                        20
     D  ReplaceObj                    1
     D  ErrorCode                    16

     D FromObj         S             20    inz('TESTOBJ   *CURLIB   ')
     D FromType        S             10    INZ('*PGM      ')
     D ToObj           S             20    inz('NEWOBJ    *CURLIB   ')
     D ReplaceObj      S              1    inz('1')
     D ErrorCode       DS
     D  BytesProvided                100 inz(%size(ErrorCode))
     D  BytesAvail                    4
     D  ExceptionID                   7
     D  RESERVED                      1
     D  ExceptionData               256
      /free
       RenameObj(FromObj : FromType : ToObj : ReplaceObj : ErrorCode);
       dsply ExceptionID;
       dsply %subst(ExceptionData:1:52);
       *inlr=*on;
      /end-free
  

[{"Product":{"code":"SWG60","label":"IBM i"},"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Component":"Programming (Languages- compilers- tools)","Platform":[{"code":"PF012","label":"IBM i"}],"Version":"Version Independent","Edition":"","Line of Business":{"code":"LOB57","label":"Power"}}]

Document Information

More support for:
IBM i

Software version:
Version Independent

Operating system(s):
IBM i

Document number:
667555

Modified date:
17 June 2021

UID

nas8N1021648

Manage My Notification Subscriptions