Run-time errors occur when the program is executed. These errors are not detected by the compiler, because the code is syntactically correct.
An example of a run-time error is a statement that causes
division by zero. In the following statement, the syntax is
correct, but the statement may cause a division by zero error if
Second_number is assigned a value of
Ratio := First_number / Second_number;
The common trait of these errors is that the code works correctly in many situations, but fails in others. The risk is that since there is nothing syntactically wrong with the code, the error could occur when the program is already in use. Unless you handle the run-time error in your code, default messages will appear.
Run-Time Errors and Data Consistency
There may be instances when run-time errors can compromise the integrity of the database. For example, if some fields are updated in a trigger and a run-time error occurs while other fields have not been updated. When a trigger is entered, a write transaction begins. If a run-time error occurs inside the trigger, the write transaction is rolled back and the execution of the trigger is terminated.
How to Avoid Run-Time Errors
The following guidelines show how to avoid run-time errors. These are only guidelines, as the conditions under which run-time errors occur are dependent on the context of your application.
If, for example, you use the GET function to locate a record, you must be prepared handle the possibility that a run-time error can occur if there are situations where no record is found. If you are certain that the specific context precludes this situation, you can omit handling a possible run-time error. (The context could be that the existence of a record is verified before the GET function is used.)
There are two categories of run-time errors:
Errors that are related to the use of data types
Errors that occur if a function does not succeed in doing what it is supposed to do
Division by zero does not fit into either of these categories, but it has been placed in the first one.
You can only prevent some errors (mainly related to data types) from occurring. Other errors cannot always be avoided, but you can write code that shields the user from the error. Instead of the default error handling (which displays a message, closes the form that was active when the error occurred, and rolls back any changes to the database), you can write an error handler that, for example, gives the user an opportunity to correct the input that caused the error. This error will display a message that explains why the error occurred.
Data Type-Related Errors
The easiest way to avoid data type-related errors is to use the correct data types. Errors like the type conversion error in the previous example and overflow errors can be avoided by using the correct data types.
A division by zero error can be avoided in several ways,
depending upon the context where the code fragment is used. If the
user enters the denominator (the
variable) in a text box immediately before the evaluation of the
statement, you could test the value of
before performing the division, and reject a value of 0 (zero):
IF Second_number <> 0 THEN
Ratio := First_number / Second_number
MESSAGE('Second_number must not be 0');
Second_number is a field in a database table,
and it should never be allowed to have a value of 0 (zero), the
best place to perform this check is in the
trigger of the field. This enables you to ensure that a value of 0
(zero) can never be entered in the field.
Other Run-time Errors
Any function that fails to accomplish what it is intended to do can cause a run-time error. A good example is the GET function, which is used to locate a record in a table according to criteria that you specify.
The syntax of the GET function is:
[Ok :=] Record.GET([Value1], [Value2 ],...)
The return value of the function is
Ok, a Boolean.
If a record is found, the return value is TRUE; otherwise,
it is FALSE. This return value can be ignored, as indicated
by the square brackets. If it is ignored and the requested record
cannot be found, a run-time error occurs and a system-generated
error message is displayed. However, if you test the return value
and a run-time error does not occur, it is assumed that you handle
the condition yourself.
Ok. If it does, consult the to see which functions return a Boolean for other
reasons than those described here. For example, the
ASCENDING function can be used to check the sort order
of a table. In this case, it returns TRUE if the sort order
is ascending, and FALSE if it is descending.
If you use the return value in either of the following examples, you can shield the user from a run-time error.
IF NOT Customer.GET("No.") THEN
IF NOT Customer.GET("No.") THEN
MESSAGE('Customer %1 not found', "No.");
In the first example, if a Customer record with the given number
(No.) cannot be retrieved, an (empty) record is initialized. In the
second example, the user is notified that the record cannot be
found and the trigger from where the
GET function was
called is exited. These examples are only general guidelines. You
must consider how to handle situations like these in the context of
your own application.
Finding and Correcting Run-time Errors
To determine the cause of a run-time error, you need the exact description of the sequence of events that led to the error. The sequence of events should include the following:
What the user was doing at the time of the error
What values the user entered
What record caused the error
If the error was caused by a calculation that failed to check whether a division by zero was about to be carried out, you should be able to find the statement that led to the error. However, if the circumstances that led to the error are more complicated, and you cannot determine the exact location of the error, you can use the debugger.