Error Handling

Sometimes the code throws a runtime exception (e.g. unexpected null value, invalid number format, …​). Such exceptions can be handled using one of the following approaches:

Try-Catch Statement

You may use the try-catch statement to handle runtime errors.
For every try statement, there can be only one catch block as there is only one type of exception: CTLException. Additionally, there is no finally block. In CTL, there are two parts to try-catch statement:

  • try block allows you to define a code to be tested for errors
  • catch block’s purpose is to handle errors that might occur within the try block

Depending on whether the try block encounters an error or not, the execution of the statement may lead to two alternatives:

  • If the try block executes without errors, the following catch block is skipped, and the whole try-catch statement completes successfully.
  • If the code inside the try block is erroneous, the execution jumps to the beginning of the respective catch block and executes the code within it.

The implementation of how to handle the error is up to you. For example, you can throw a custom error using the raiseError() function, log the exception and have the execution finish successfully, or execute a custom code as a workaround for the exception. You can access some details about the exceptions via the CTLException data structure.

try-catch statements can be nested.

Example 75. Try-Catch Statement

integer a = 123;
integer b = 0;
integer c;

try {
    c = a / b; // throws ArithmeticException
    printLog(info, c); // skipped
} catch (CTLException ex) {
    c = -1; // workaround: set the variable to -1 to indicate error
    printLog(warn, ex); // log a warning
}

CTLException is actually a data record with the following fields:

sourceRow: integer
the row of the CTL source code where the exception occurred

sourceColumn: integer
the column of the CTL source code where the exception occurred

message: string
the error message of the innermost exception - the original cause of the failure

cause: string
the type of the innermost exception, e.g. java.lang.ArithmeticException

stackTrace: list[string]
the cascade of function calls that caused the failure

exceptionTrace: list[string]
the list of exception types from the outermost to the innermost

OnError() Functions

Alternatively to the Try-Catch Statement, you can use a set of optional OnError() functions that exist to each required transformation function.

For example, for required functions (e.g. append(), transform(), etc.), there exist following optional functions:
appendOnError(), transformOnError(), etc.

Each of these required functions may have its (optional) counterpart whose name differs from the original (required) by adding the OnError suffix.

Moreover, every <required ctl template function>OnError() function returns the same values as the original required function.

This way, any exception that is thrown by the original required function causes call of its <required ctl template function>OnError() counterpart (e.g. transform() fail may call transformOnError(), etc.).

In this transformOnError(), any incorrect code can be fixed, an error message can be printed to the Console, etc.


Remember that these OnError() functions are not called when the original required functions return **Error codes** (values less then -1).
If you want some OnError() function to be called, you need to use the raiseError(string arg) function. Or (as stated before) any exception thrown by original required function calls its OnError() counterpart as well.