Tiago Ribeiro · Feb 18, 2016

Message Error - CSP.Page

The cache has error messages default, for example , " -139 SQLCODE : Competition impairment on the update: row versions are not the same. "

How i can exchange it for a more friendly to the user's message? I use the CSP.Page and form_save ( ).

What is best practice for this situation?

2 0 3 846
Log in or sign up to continue


Yes, it is possible, but you should be ready to change it after all updates of Caché

Read about it in documentation  - Localizations

In first you should export current localization 

DO ##class(%Library.MessageDictionary).ExportDomainList("messages_sqlcode_en.xml","%SqlCode","en")

here %SqlCode, it as a domain for Sql Codes. And any language which you want to change.

then you can change any text in this xml, and should keep all off tags with their Id attribute, if you delete some tag, you will loose their localization. And then you can import your new localization. As it system localization, you have to allow writing to CACHELIB database.

do ##class(%MessageDictionary).Import(&quot;<code class="COS">messages_sqlcode_new_en.xml

You have to remember that it is a system localization, and InterSystems can change it, add or remove anything here, and in every new version, you should follow theri changes.

Or much simple way, it just set new value directly to  the global.

USER&gt;set ^%qCacheMsg(&quot;%SqlCode&quot;,&quot;en&quot;,&quot;SqlCode139&quot;) = &quot;TEST Concurrency failure on update: row versions not the same&quot;
TEST Concurrency failure on update: row versions not the same


Specifics on %CSP.Page / cspbind error handling:

There are alternatives to modifying system-level error message translations. Even if the localization is changed, the end user would probably still see "SQLCODE -139," which isn't helpful. What you probably want to show the user is "Someone else has modified this record. Please reload the page and try again." or something similar.

Using %CSP.Page and a form with cspbind, there's no way to customize the error handling in the generated <form name>_save function. It seems to always show any error message in an alert. An alternative would be to use a similar approach to form.csp and formsubmit.csp in the SAMPLES namespace, submitting the form and calling the <form name>Submit method of the page rather than using a hyperevent (in form_save()). Note that you don't need a separate page to handle the form submit; one page can do it all.

Of course, if the form is saved with a POST rather than a hyperevent, and optimistic concurrency control is in use, it might be worth a separate call to the server immediately before submitting the form for an optimistic concurrency check. If someone else edited the record, the page could tell the user rather than submitting the form. This wouldn't prevent the error in question, but would at least make it much less likely.

(Side note: %CSP.Page/cspbind is very old technology. There are better tools available now, but if you're stuck with it in a large existing project, that's understandable.)


General thoughts on showing users friendly error messages:

The more general problem is: "Often, the error codes and messages the system produces are not helpful to an end user. How do you show the user the information they need when an error occurs?"

This gets more complicated because error messages can come from very different sources - for example, SQL, an object %Save, a variable being undefined, or the application detecting a user error.

The standard for the large Caché-based application I work on is:

  • Within UI classes (class-based CSP or Zen, in our case), server-side code is wrapped in try-catch blocks.
  • Different types of exceptions (subclasses of %Exception.AbstractException) are thrown for the different types of errors that occur. These may be:
    • SQLCODEs and associated messages from embedded or dynamic SQL
    • Error %Status codes from object %Saves and various other things
    • General internal errors in application business logic
    • User errors detected in business logic. (These are treated differently for logging purposes; user errors may be more common than system errors and might not be logged.)
    • System errors (<UNDEFINED>, <SUBSCRIPT>, etc.)
  • Any of these types of exceptions. except system errors, may include a user-friendly message explaining what went wrong.
  • If an exception is caught, a method is called to (1) log that an error occurred and (2) either provide a description of the error that the user can understand, or else just say that an error happened (with the confusing details omitted, although they are logged).
    • If the exception already has a friendly message for the user, it's returned.
    • Otherwise, for error SQLCODEs and error %Status codes, we provide general messages for concurrency-related errors and some other common error codes. We also have a system for interpreting foreign and unique key violations (from an SQLCODE or %Status) and providing more descriptive messages based on those.
    • Worst case, the message "An internal error occurred (log ID _____)" is returned.
  • The message is shown to the user in red text, an alert dialog (ideally not a vanilla JavaScript alert), or however else makes sense in context.
  • There are macros for the different types of exceptions and for getting the user-friendly message, for ease of maintainability.