How do your scripts and layouts help users handle errors?

A little background: I'm trying to branch out from FileMaker a little and learn more about computer science and software engineering in general. In an engineering course I am taking, we looked at Nielsen's 10 heuristics for interface design. One of them is:

Help users recognize, diagnose, and recover from errors:
Error messages should be expressed in plain language (no codes), precisely indicate the problem, and constructively suggest a solution.
Heuristic evaluation - Wikipedia

(This is on my mind because I am recovering from an error on a Windows server where the whole error message is "Windows could not start the FileMaker Server service on Local Computer. Error 1003: Cannot complete this function." That's not a very helpful error message :upside_down_face: I give it a score of 1 out of 3: It does use plain language, but also an error code that searching the web and documentation has not given me any more information, and it does not suggest a solution.)

I've realized that I handle errors different in my layouts for end users and in my scripts. In my user interfaces I rarely indicate the problem, but I think I do a good job explaining the problem and how to fix it. My error handling is pretty poor in my scripts though. I'm the only person who currently works on this database and I know I should be writing clearer code and better comments to help future me and future developers. Doing a little C++ development has given me some new ideas about how I might approach error handling in scripts.

What approach do you take to making scripts and layouts that signal errors to users (end users, other developers, yourself) and guide the users to handle the errors?

5 Likes

Funny that you should post this. I have been working on this subject for a while now.

First thing… reduce errors as much as possible. By that I mean trap for input problems before invoking any script that does useful work. That said, there will come a time when, no matter your input checking, the system will produce an error. That's where error trapping comes in and user communication is inevitable.

My business uses what we call a result management framework. It is an evolution of a solution I developed over 10 years. It manages many common error and result tasks, works with calculations and scripts, has the means of communicating with both users and developers and offers many other features. The communication feature is the only one I will detail as it is pertinent to you and this thread.

The framework has the capability to override standard error message with custom text. It can also display an error message with a button that allows the user to see the technical information. If the user opts to display the technical information, the user has the further option to copy this information (for use in an email to technical support, for example). In addition, it has the ability to create an error chain, the list of errors that produced the final error.

Error handling is not a freebie. By that I mean that coding effort must be expended to trap errors, send them up the execution stack and then display the message to the user while at the same time preserving the error chain. The framework facilitates this but does not do everything. Considering some errors may not be critical or important (error 401, for example), this could be a good thing.

I am in the process of updating the framework's documentation. I am in talks with customers and with a training facility to offer a course for the use of this framework. I am limited to remote learning at the moment due to COVID-19. I may look into classroom learning eventually if demand justifies it. Lastly, I am looking at ways to license this framework.

As in all things, there is a tradeoff. The framework has been time-tested. That said, there could still be errors. These will be difficult to troubleshoot during code execution due to the abstraction introduced by the framework and its heavy use of custom functions and structures.

Hope that helps. The framework is unavailable at this time. That said, I am curious to know if there is interest for such a thing… so please let me know. Feel free to message me for more information.

2 Likes

The user is the last person you'd go to for help to fix a problem, so why make them the first person to know about them?

Most errors can and should be handled sensibly without any interaction with the user.

If you are running your databases on FMS then you have access to logs which will tell you a lot about what is happening. These also provide you with great insight into what you can do.

In my case, the most common message I found in my server logs was 101 - Record is missing. If a user was shown this message each time it occurred they would push their machine off the desk!

A 101 is generated by (1) looping through records with the script step Go to Record [ next ; exit after last ] and (2) when GTRR is used and there is nothing on the other side of a relationship. I code the Go to Record loops to ensure 101 errors are not generated and I test for the presence of related records before using GTRR.

Another low hanging fruit is error 1 - User cancelled action. If a dialog includes an Cancel button, it will get pressed. Whenever a dialog is presented, test the result, capture the error and stop or roll back as required.

There will always be a situation where we have to tell the user that something has gone wrong but make them as rare as possible. And don't expect the user to be interested or care. Capture all the details you can then use a layout or a custom dialog to inform the user. I favour a custom dialog titled "System Alert" that says "Please inform your IT support that a problem occurred .... and the error has been logged" with a "Details" and an "OK" button. The three dots are replaced by something simple, like "printing failed" or "disk space is low". The details button will reveal the information that has been logged.

Whether you log the information to the system logs or to a table within the database will depend on the circumstances. As much as possible I like to use the system logs but in some situations it is easier to log to a table within the db.

2 Likes

The thread does not suggest that users be the first to know about an error. Some errors can be handled gracefully without the user's knowledge, the low hanging fruits as you call them, and the not so low. That's error handling and the original posts assumes we perform it. That situations exist where the user must be informed of errors is implied by the original post. The communication mechanism and the message are the interests of this post.

Why did the operation fail? Is it a failure that requires outside help or is there something the user can do to remediate the issue? For example, a selection quantity that exceeds available stock (a business logic error), an unknown product code (a 401 error) and an invalid credit card number (validation error) do not require developer help. On the other hand, a file that failed to open (error 100), an expired SSL certificate (error 1632) and a failure to create a file (error 800) likely require the user to know that the issue requires the help of a technician or developer.

An error log table mechanism for failures that require outside help is an oft used technique that I use from time to time. It is especially useful when its data can be analyzed. Its downsides, to me, are the need to manage the log and its weakness to disk and network issues. That is why I write diagnostics data to memory. If all else fails, there is still a chance I can get the user to contact the developer.

1 Like

I'm stoked to see a convo about errors!

  1. Trap for errors after everything that can throw an error. This is about the script having awareness of error codes, not how those errors are handled. A script is free to ignore certain errors, but it should do so consciously.
  2. Trap for "app" errors, that is errors that violate business logic or constitute special handling in the script. E.g. a script tries to create a record without a required parameter.
  3. Handle the error. This could mean waiting and retrying a step, reverting a transaction, exiting early and showing a dialog, prompting the user to correct something, or even emailing the developer automatically that an unexpected error occured.
  4. Log errors. These logs should get written to a central logging file and enough information should be written about the error that if you, the developer, sees the log you can correct the error without even needing a call from the user.
  5. (this has already been said, but bears repeating): avoid bothering the user if you can about errors unless they are the only one who can fix them (like the invalid credit card example above)

This usually requires using a standard error format and and script flow pattern. E.g. karbon has a set of published error functions, which are a fair start. And single-pass loops for error trapping (essentially try-catch loops) are great for controlling script flow, especially in relation to errors.

Unfortunately FM doesn't have a native try-catch structure so scripts that properly trap for and handle errors often end up about twice as long as normal scripts (one Exit Loop If[] after each step), but the upside is you usually get to stop worrying about these scripts after they're written because, with proper logging, they'll tell you when an error occurs, and where.

5 Likes