Collectible Errors?!

by Jul 16, 2022AL Language

Home 9 Development 9 AL Language 9 Collectible Errors?!

Collectible Errors?!

It has been already almost a year since ErrorInfo datatype & CollectibleErrors were introduced (I already have an article about basic structure: ErrorInfo data type & Collectible Errors). This article was released for the first time in September 2021 before this functionality was publicly available. Since then, there have been some changes and fixes I have already added to the original article.

Today, I want to look at some examples and see how to use collectible errors, how it differs from standard errors we have known for years, and how to use it. Later (probably in two separate articles in the upcoming weeks), I’ll show you more advanced examples of collectible errors (with the rest of the parameters) and some examples of actual usage of collectible errors and also how (and where) it is already used in the Base App.

Examples

Standard Errors

Let’s start with a basic example, with the standard error (..) procedure we all know and have used for ages. The example below is easy; calling the procedure will raise the first Error, and the whole process stops. The second Error won’t be executed (and warning AA0136 will be shown).

local procedure Error1()
begin
    Error('Test error 1');
    Error('Unreachable code.');
end;

In the example below, we get the same result with the ErrorInfo data type. In this type, we use the new Error(ErrorInfo) method (the difference is that the “old” method accepts text as a parameter, this new, overloaded method accepts ErrorInfo data type). But the result is absolutely the same – the first Error is raised once the method is called, and the second Error is unreachable.

local procedure Error2()
begin
    Error(ErrorInfo.Create('Test error 2'));
    Error(ErrorInfo.Create('Unreachable code.'));
end;

Collectible Errors

To start using collectible errors, we have to be familiar with two terms.

The procedure that should use CollectibleErrors needs to be decorated with the ErrorBehavior attribute ([ErrorBehavior(Behavior: ErrorBehavior)]). Right now, the only value available for ErrorBehavior enum is Collect. So if you want to enable collectible errors for a specific method, write [ErrorBehavior(ErrorBehavior::Collect)] before the procedure. If you do not want collectible errors (= want the standard error behavior when the error is raised once the line with Error is executed) simply do not use this parameter.

However, even with this parameter, errors will still be raised once the code executes them. So the example below is still the same even with [ErrorBehavior(ErrorBehavior::Collect)] and both Error(Text) and Error(ErrorInfo) methods work in the same way.

[ErrorBehavior(ErrorBehavior::Collect)]
local procedure Error3()
begin
    Error(ErrorInfo.Create('Test error 3'));
    Error(ErrorInfo.Create('Unreachable code.'));
end;

// OR

[ErrorBehavior(ErrorBehavior::Collect)]
local procedure Error3B()
begin
    Error('Test error 3');
    Error('Unreachable code.');
end;

So what’s the second term I said you need to be familiar with?

It’s “Collectible“! Because only errors marked as Collectible are collected in methods defined with [ErrorBehavior(ErrorBehavior::Collect)]. How to define Error as collectible? It’s easy, but there is a difference between Error(Text) and Error(ErrorInfo) methods – only the second one, Error(ErrorInfo), can be set as Collectible. It’s the second parameter in ErrorInfo.Create() method just after the text of the Error.

The example below shows how to use collectible errors properly.

[ErrorBehavior(ErrorBehavior::Collect)]
local procedure Error4()
begin
    Error(ErrorInfo.Create('Test error 4', true));
    Error(ErrorInfo.Create('Test error 5', true));
end;

And how does it look from the user’s side? It seems like a standard error – the user sees there is something wrong. The message is also pretty clear – “Multiple errors occurred during the operation, the first of which is: Test error 4. All errors can be found under ‘Detailed Information’.“. As stated, under detailed information, all errors can be found. Below is the log from the error (it’s what you get once you use the “Copy information to clipboard” link in error).

/*
Multiple errors occurred during the operation the first of which is: Test error 4. All errors can be found under 'Detailed Information'.

Test error 4
Test error 5

Internal session id: 
5296a108-3f8a-4514-ae4f-a54d9a2e1947

Application Insights session id: 
ce4a57d4-1172-470c-bcee-381882638a19

Client activity id: 
0282fb25-8950-6759-064d-01cb9db6a4ab

Timestamp: 
2022-07-15T08:31:28.2756526Z

AL call stack: 
"TKA Collectible Errors Mgt."(CodeUnit 69000).Error4 line 5 - Collectible Errors by Kepty.cz, Ing. Tomas Kapitan
"TKA Collectible Errors Mgt."(CodeUnit 69000).Try line 11 - Collectible Errors by Kepty.cz, Ing. Tomas Kapitan
"TKA Customer List"(PageExtension 69900).OnOpenPage(Trigger) line 4 - Collectible Errors by Kepty.cz, Ing. Tomas Kapitan
*/

The last thing I want to cover in this article is the TestFields() method. Even this method can be used as Collectible. You are definitely familiar with the method Record.TestField(Field, [Value]) where [Value] is the value the field should have. If omitted, the method tests that the Field is not blank.

The error from this method (as the example below) can not be collected, so the error in the example is unreachable!

[ErrorBehavior(ErrorBehavior::Collect)]
local procedure Error5()
var
    Customer: Record Customer;
begin
    Customer.FindFirst();
    Customer.TestField(Name, '');

    if Customer.Name <> '' then
        Error(ErrorInfo.Create('Unreachable code.', true));
end;

To be able to collect TestFields() errors, we need to use the new method Record.TestField(Field, Value, ErrorInfo) or Record.TestField(Field, ErrorInfo). These two methods accept as the last parameter instance of ErrorInfo and use the setting from this ErrorInfo. That means, if ErrorInfo is set as Collectible, the TestField() itself is set as Collectible.

To create a new collectible instance of ErrorInfo, we can set it manually (MyErrorInfo.Collectible := true) or use ErrorInfo.Create() method (WITHOUT ANY PARAMETER!) which returns an empty ErrorInfo object that is set as Collectible.

One thing to remember – ErrorInfo.Create() is by default set as Collectible, however, ErrorInfo.Create(‘My own error’) is by default set as NonCollectible and you need to specify second parameter ErrorInfo.Create(‘My own error’, true) to create ErrorInfo as collectible!


[ErrorBehavior(ErrorBehavior::Collect)]   
local procedure Error6()
var
    Customer: Record Customer;
begin
    Customer.FindFirst();
    Customer.TestField(Name, '', ErrorInfo.Create());

    if Customer.Name <> '' then
        Error(ErrorInfo.Create('This error will be raised all times when TestField error will be raised.', true));
end;

Recent Articles from the category

NavigationAction for ErrorInfo data type

NavigationAction for ErrorInfo data type

One more article about ErrorInfo data type. Have you already read my previous posts about ErrorInfo and Collectible Errors? ErrorInfo data type & Collectible Errors | MSDyn365 Business Central - Ing. Tomáš Kapitán (kepty.cz) Collectible Errors?! | MSDyn365...

read more
Error actions for ErrorInfo data type

Error actions for ErrorInfo data type

It is already almost one and a half years since the ErrorInfo data type was introduced (we saw this data type for the first time in BC2021w2). If you do not know what it is and how to use this data type, check my previous posts: ErrorInfo data type & Collectible...

read more
Data types under the microscope: List

Data types under the microscope: List

The List data type in AL language represents an ordered collection of objects that can be accessed by their index. Unlike an Array data type, a List does not have a fixed size and does not need to have its dimension specified when it is declared. The List data type...

read more
Connect to Azure Function in BC 2022 wave 2 (v21)

Connect to Azure Function in BC 2022 wave 2 (v21)

The new version of the Microsoft Dynamics 365 Business Central brought a new system module "Azure Functions" that makes integration with Azure Functions much easier and straightforward. The typical scenario, why to use Azure Functions together with Business Central,...

read more
Collectible Errors?! Is it already in use?

Collectible Errors?! Is it already in use?

Collectible Errors?! Is it already in use? This is the second part of my new article series about Collectible Errors. Let's check out the first part here: Collectible Errors?! | Microsoft Dynamics 365 - Ing. Tomáš Kapitán (kepty.cz) or you might be interested in my...

read more
Substituting standard reports

Substituting standard reports

Report objects cannot be extended in versions previous to the Business Central 2021 release wave 1 version when ReportExtensions object was introduced. Since then, many of changes we need to do in reports can be done without creating a new copy of object. On the other...

read more

Sign Up for News

Certifications

Highest certification
Microsoft Data Management and
also in D365 Business Central

Microsoft Certified: Dynamics 365 Business Central Functional Consultant Associate

See other certifications here