Sat, Jun
4 New Articles

The API Corner: Inform Users of Problems by Sending Error Messages from Application Programs

  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Learn how to take advantage of the Send Program Message (QMHSNDPM) API to alert users to problems.


In a previous article, "What to Do with Messages in the Application Program," we looked at how to detect error conditions in a program. These conditions might be the result of an API call or an error in the application program itself. Today, we will look at one approach to informing the user that a problem has been encountered.


To do this, we will use the Send Program Message (QMHSNDPM) API. The QMHSNDPM API defines several parameters, which are shown below. The full documentation for the API can be found here.


Required Parameters Group:


Message identifier




Qualified message file name




Message data or immediate text




Length of message data or immediate text




Message type




Call stack entry


Char(*) or Pointer


Call stack counter




Message key




Error code



  Optional Parameter Group 1:


Length of call stack entry




Call stack entry qualification




Display program messages screen wait time



  Optional Parameter Group 2:


Call stack entry data type




Coded character set identifier



  Default Public Authority: *USE

  Threadsafe: Yes

The first parameter, Message identifier, can be either blanks for an immediate message such as "Good morning" or the identifier of a predefined message description (such as CPF9810). While the QMHSNDPM API can send a wide variety of message types (diagnostic, completion, status, etc.), we are interested today in sending escape messages. When sending escape messages, the API requires that the message is predefined, so we will need to create a message file and a message description. The CL command to create the Application Messages message file APPLMSGF in library QGPL is this:




The command to add message description APP0001 to APPLMSGF is this:



     MSG('Severe error found in program &1. Notify your support personnel.') +

     SECLVL('Review the job log for previous error(s) that have been logged.') +     

     SEV(99) FMT((*CHAR 10))       


In our initial use of the QMHSNDPM API, we will use message identifier APP0001 to report unexpected errors in the running of our application.


The second parameter, Qualified message file name, is the names of the message file and the library where the message identifier specified in the first parameter can be found. We will use message file APPLMSGF in library QGPL.


The third parameter, Message data or immediate text, is used to specify replacement variable information that is to be inserted into a predefined message. Message description APP0001 defines one substitution variable (&1), which represents the name of the program encountering the failure. This substitution variable is defined as a 10-byte character variable. In our sample program, we will access the program name using RPG's Program Status Data Structure (PSDS). The message description can have up to 99 substitution variables of various data types (binary, packed decimal, character, etc.), so you have quite a bit of flexibility in what other information you might want to include in the error message text. For an immediate message, this is also where you would provide the impromptu message text (such as "Good morning").


The fourth parameter, Length of message data or immediate test, is the length of the data sent to the API using the third parameter.


The fifth parameter, Message type, identifies the type of message being sent. As mentioned in reviewing the first parameter, the QMHSNDPM API can send a variety of message types. The sample program will be sending escape messages (type *ESCAPE).


The sixth and seventh parameters, Call stack entry and Call stack counter, respectively, are used to identify where the message is to be sent. The sixth parameter identifies a call stack entry (an OPM program or ILE procedure) within the current job, and the seventh parameter identifies a relative counter based on the call stack entry identified by the sixth parameter. If, for instance, the Call stack entry identifies the current procedure calling the QMHSNDPM API and the seventh parameter is set to 0, then the message is sent to yourself. If the Call stack entry identifies the current procedure and the seventh parameter is set to 1, then the message is sent to the caller of the current procedure (the call stack entry one previous to the current procedure or OPM program). Several special values are supported for the Call stack entry parameter. The special value of asterisk (*) can be used to indicate that the current procedure (or OPM program) should be used. The asterisk (*) special value is what would typically be used in the previous example scenarios. Another special value is *PGMBDY, which indicates that the message should be sent to the oldest (or first) call stack entry for the program (or service program) currently running. It is this special value our sample program will be using along with a Call stack counter value of 1. This combination will cause the escape message sent by the sample program to be sent to the caller of the current program (or service program).


Using *PGMBDY and a Call stack counter of 1 can simplify the reporting of an error when your program has multiple procedures as the message will be sent directly to the caller of the program. This can be important when your program has a main procedure (A) that calls one or more subprocedures (B, C, D, etc). Having the subprocedure directly send the escape message to (*PGMBDY + 1) avoids having intermediate procedures "see," and then have to handle, the error message. By analogy, if you have ever had subprocedure B set on *INLR and then return to procedure A, you quickly find out that procedure A is quite happy to continue running. Procedure A, in order to stop processing, must check for *INLR and also return if the program is to end. Using (*PGMBDY + 1), you can avoid having A try to report an error that B has already reported.


The eighth parameter, Message key, is the key assigned by the system to the message being sent. This value will not be used in the sample program.


The ninth parameter, Error code, is the standard system API error code parameter.


The remaining parameters are not used by the sample program, though you may want to review them in the Information Center to get a feel for some of the other features available to you when sending a message.


Returning to the program of the previous article, at the end of the main program/procedure, there is a global on-error block to catch all unexpected errors that might occur. These might be errors such as MCH0603 – Range of subscript value or character string error, MCH1211 – Attempt to divide by zero, or a CPF message resulting from an API call where the error code Bytes provided field is set to zero. In these situations, the error message is already in the job log and we want to end the program with a message such as the previously created APP0001. The following program additions will do just that.


We will start by providing a prototype for the QMHSNDPM API. Here's the prototype, named SndMsg:


dSndEscape        pr                  extpgm('QSYS/QMHSNDPM')  

d MsgID                          7    const                    

d QualMsgF                      20    const                    

d MsgDta                     65535    const options(*varsize)  

d LenMsgDta                     10i 0 const                    

d MsgType                       10    const                    

d CallStackEntry             65535    const options(*varsize)  

d CallStackCntr                 10i 0 const                    

d MsgKey                         4                             

d QUSEC                               likeds(QUSEC)            

d LenCSE                        10i 0 const options(*nopass)   

d CSEQual                       20    const options(*nopass)   

d DSPWaitTime                   10i 0 const options(*nopass)   

d CSEType                       10    const options(*nopass)   

d CCSID                         10i 0 const options(*nopass)   


As we need the program name for the substitution variable &1 of message description APP0001, we will also define a program status data structure.


dPSDS            sds                  qualified

d PgmName               334    343             


And as the QMHSNDPM API provides the Message key as an output parameter, we will define a standalone 4-byte character variable MsgKey even though the sample program will not utilize the message key.


dMsgKey           s              4 


Optionally, the program will also define a qualified data structure to hold the substitution variables for each message that might be sent. My convention is that the name of the data structure is the same as the name of the message description.


dApp0001          ds                  qualified    

d PgmName                       10                 


Strictly speaking, this data structure is not necessary as there is only one substitution variable, but I find it helpful to have a standard in place that the replacement data for any given message can be found in a data structure of the same name. A data structure typically is needed when multiple substitution variables are used in a message (as they all must be passed as one contiguous value in the third parameter of QMHSNDPM), and I can then also consistently use the %size of the data structure as the fourth parameter of QMHSNDPM.


With the previous definitions in place, we will now insert a call to the QMHSNDPM API in the program's on-error block.



   // Any additional work you might want to do                 

   App0001.PgmName = PSDS.PgmName;                             

   SndMsg( 'APP0001' :'APPLMSGF  QGPL' :App0001 :%size(App0001)

          :'*ESCAPE' :'*PGMBDY' :1 :MsgKey :QUSEC);            



Now, when the program encounters any unexpected error, the on-error block will send the escape message APP0001 to the program's caller, indicating that an error occurred and that the job log contains additional information. As the message type is *ESCAPE, the program will end immediately (that is, control will not be returned to any statements following the SndMsg API call). As control will not be returned to the program, any additional processing you might want to do, for instance using the DUMP(A) operation, needs to be done prior to calling the API.


If the sample program is named SNDESC and a divide-by-zero error is encountered, the following two messages will be found in the job log.


Attempt made to divide by zero for fixed point operation.          

Severe error found in program SNDESC. Notify your support personnel.


The first message is sent by the system identifying the underlying problem. The second message is sent by the application program.


The previous article also discussed, within the context of determining if an object exists and, if not, creating it, using an API error code parameter that disabled the sending of escape messages from an API. This disablement is accomplished by using an error code Bytes provided value of 8 or more.


If escape messages from an API have been disabled and an unexpected error is encountered (for instance, from the previous article, CPF9820 – Not authorized to the library), then the program needs to do more than just send the APP0001 error message. This is because the CPF9820 error message was never actually sent, so the support personnel will not find any additional information in the job log—a rather frustrating experience!


In this situation, we could call the failing API a second time, this time with escape messages enabled. But there is a better solution—namely, using the QMHSNDPM API to send the original escape information that the API would have sent had escapes not been disabled. In the next article, we will look at how to accomplish this.


In the meantime, if you have any API questions, send them to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll see what I can do about answering your burning questions in future columns.




Bruce Vining

Bruce Vining is president and co-founder of Bruce Vining Services, LLC, a firm providing contract programming and consulting services to the System i community. He began his career in 1979 as an IBM Systems Engineer in St. Louis, Missouri, and then transferred to Rochester, Minnesota, in 1985, where he continues to reside. From 1992 until leaving IBM in 2007, Bruce was a member of the System Design Control Group responsible for OS/400 and i5/OS areas such as System APIs, Globalization, and Software Serviceability. He is also the designer of Control Language for Files (CLF).A frequent speaker and writer, Bruce can be reached at This email address is being protected from spambots. You need JavaScript enabled to view it.. 

MC Press books written by Bruce Vining available now on the MC Press Bookstore.

IBM System i APIs at Work IBM System i APIs at Work
Leverage the power of APIs with this definitive resource.
List Price $89.95

Now On Sale



Support MC Press Online

$0.00 Raised:

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: