In a typical Valence app you have a myriad of front-end UI logic working in tandem with back-end RPG programs that process AJAX calls and perform functions to retrieve or update IBM i data. Whenever something goes wrong on the front-end, you can typically zero in on the issue by peering into the browser's console. But when an unexpected error or problem occurs on the IBM i back-end — whether it be a trapped condition in a program, or a critical error like a record lock or a divide-by-zero scenario that throws the CGI job into MSGW status — there is of course no console on the browser to look at. In these cases the Valence Errors app is a good first place to check when figuring out what went wrong. You can also set up your own internal apps to log exceptions into this error log, and when necessary you can throw an accompanying exception message up for the user letting them know an error has occurred.
This tip explains how. The Errors app is simply an inquiry app over the VVERRLOG file. Every program comprising both the Valence Portal and the Valence RPG Toolkit uses this file to store pertinent exception information.
Some of the most common issues that are logged in the Valence Errors app include:
- Apparent portal security violations, such as AJAX calls that don't have a valid session ID, or attempts to use an invalid/expired developer token
- Invalid SQL statements processed through vvOut_execSQLtoJSON
- Attempts by the front-end to call a back-end RPG program that is neither specifically authorized to the app in Portal Admin > Apps, nor set up as a program that bypasses authority checks in Portal Admin > Settings
- Attempts to call a PHP or Java program in a path that is neither specifically authorized to the app in Portal Admin > Apps, nor set up as a path that bypasses authority checks in Portal Admin > Settings.
- API exceptions encountered on any vvIFS calls
- Exceptions encountered when attempting to cast posted parameters through vvIn, such as trying to pop a character value into vvIn_num() or an invalid date into vvIn_date()
- Any invalid or missing configurations passed into vvIn or vvOut via the respective data structures.
- Any exceptions encountered when migrating data from older versions of Valence via VVMIGRATE
Additionally, any CGI job that goes into MSGW status will log the error condition in Errors app, though you may need to look at prior messages in the job log of the affected job to fully diagnose the root cause. The call stack of the affected job is also stored with each error, which may assist developers with locating the program that caused the problem. Whenever possible and practical, any trapped, critical back-end errors encountered will notify the front-end that an error condition was encountered. This is done by sending a special status code of 569 in the HTTP response, which is intercepted by the Valence Portal and triggers a pop-up window to be presented to the user.
Note that when a job goes into MSGW status it is not possible to send a response to the front-end since the CGI job is interrupted, though the error condition is still logged in VVERRLOG. The Valence procedure to handle message logging on the back-end is vvUtility_logError(), which can be called by any RPG program to log messages into the Valence Errors app and/or send a pop-up notification to the user in the Valence Portal with information pertaining to the error. Let's dig into the documented example code and expand on some of its uses:
d err e ds extname(vvErrLog) qualified /free // user just performed a major no-no. Log the error, pop up an error message and tell their session to end... err.vvMsgTxt = 'User entered something terribly obscene.'; err.vvHlpTxt = 'The data this user typed is so obscene he must be logged out.'; err.vvPgm = 'PRODMAINT'; err.vvProc = 'SAVE_PROD'; err.vvStmt = 120.25; vvUtility_logError(err:0:'ERROR':'genericMsg': %ucs2('You just pulled a major no-no and must now log out'): 'LOGOUT'); /end-free
The first parameter on this procedure ("err") is a data structure modeled after the VVERRLOG file itself. You can *omit this parameter altogether to skip logging data to the error log and send just a pop-up message to the front-end based on information specified in subsequent parameters. Otherwise, you would typically populate some or all of the following data structure fields:
- VVPGM - the name of the program or service program in which the error occurred
- VVMODULE - the name of the module in which the error occurred (this is useful for service programs consisting of multiple modules)
- VVPROC - the name of the subprocedure in which the error occurred
- VVSTMT - a specific statement identifier that might be helpful for a developer tracing the error (does not necessarily have to be a source code record number).
- VVSEV - the relative severity of the message, a number between 00 and 99 (this can be useful for querying VVERRLOG for certain types of messages)
- VVMSGTXT - a summary of the message (256 characters max). This is treated essentially as the message header.
- VVHLPTXT - additional details behind the message (4096 characters max)
The second parameter of the procedure is generally not used unless calling a C API, in which case the API error code can be specified to automatically populate the VVMSGTXT value. But in most cases you would just specify a zero value here. The third parameter, if specified, represents a literal value to be presented to the user as the header of a pop-up window. Literals are stored in /valence-5.0/packages/local/valence-locale/src, and a common one to use for the header is the "ERROR" literal (which would show as "Error" when logged into the portal in English), or the "warning" literal (which would show as "Warning"). The fourth parameter is where you can convey the pertinent details behind the error condition to the user in the pop-up window. If you want to dynamically construct the message text from within your RPG program, an easy way to do this is to specify a value of "genericMsg" here. The genericMsg literal consists of a single string value of "VAR1" that is substituted with the text specified in the subsequent fifth parameter.
Note that a double byte character field value is expected here, which typically means you'll be wrapping your text or character field inside the %UCS2() function, as demonstrated in the sample code above. The sixth and seventh parameters are typically omitted unless the literal in the fourth parameter has a VAR2 and/or VAR3 substitution value. These two are double byte character fields. The seventh parameter can be used to send one of two special actions to the Valence Portal. A value of "LOGOUT" will trigger the portal to automatically log out the user once they've acknowledged the message in the modal pop-up window; A value of "RELOAD" will trigger the portal to reload the user's launch pad, which can be useful if the exception condition has resulted in a change to the list of available apps the user can launch.
Finally, an optional eight parameter can be specified with a value of "1" in the event the error message is intended as a response to a web service call, in which case the calling entity is typically not the Valence Portal. In such cases an HTML response will be sent for the error message header and body instead of a JSON response.