In case you haven’t seen an actionable error yet, here is one:

With Business Central 2023 wave 2, AL developers got a tool, part of the platform, to provide more useful errors to users.
Just throwing an error “Account No. is missing in Table ….” is no longer the best way to help the user.
Or, errors like “Quantity can not be more than 100” is maybe less useful than a “Quantity can not be more than 100. Set it to 100”.
In Business Central, actionable errors are designed to help users identify, navigate to, and resolve errors more efficiently. These errors can be broadly categorized into two types:
- Fix-it Errors: These occur when the error location is on the current page, and the solution is straightforward and known. The error message provides a direct action to fix the issue. For example, if a quantity to invoice exceeds the allowable amount, the error message might include an action to automatically adjust the quantity to the maximum allowable value.
- Show-it Errors: These occur when the error location is known, but the exact fix is not. The error message includes a navigation action that takes the user to the relevant page where the error can be corrected. For instance, if there’s a missing value in a related table, the error message can include a “Show” action that takes the user directly to that table to enter the required data.
Actionable errors improve user experience by providing clear guidance and actions directly within the error message, reducing the need to search for the source of the problem or how to fix it. This feature helps save time and ensures tasks are completed more efficiently.
Let’s see how that transpire in code.
I took a simple example: City and Postal Code on Customer Card.
Use Case 1
On the customer card, if the value in the City field is missing, then show the list of Cities. Well, is the list of Postal Codes that includes the field City.

Here is the sample code for a “show it” use case:
[EventSubscriber(ObjectType::Table, Database::Customer, 'OnAfterValidateEvent', 'City', false, false)]
local procedure OnAfterValidateCity(CurrFieldNo: Integer; var Rec: Record Customer; var xRec: Record Customer)
var
PostCode: Record "Post Code";
ZipCode: Code[10];
InvalidPostCodeErrorInfo: ErrorInfo;
ShowCitiesErrorInfo: ErrorInfo;
begin
if Rec.City = '' then begin
ShowCitiesErrorInfo.Message('Please select the City');
ShowCitiesErrorInfo.AddNavigationAction(
StrSubstNo('Show Cities')
);
ShowCitiesErrorInfo.PageNo(Page::"Post Codes");
Error(ShowCitiesErrorInfo);
end;
end;
Use Case 2
City is filled up. And for the city there is only one postal code.
We want the user to be presented with the error if Postal Code is “” but also with the opportunity to fix the Postal code with an action: Set Post Code to “value” where value is the postal code of the unique record in Post Code table for current City.

Check the bolded code below for a “fix it” approach to the displayed error:
[EventSubscriber(ObjectType::Table, Database::Customer, 'OnAfterValidateEvent', 'Post Code', false, false)]
local procedure OnAfterValidatePostCode(CurrFieldNo: Integer; var Rec: Record Customer; var xRec: Record Customer)
var
PostCode: Record "Post Code";
ZipCode: Code[10];
InvalidPostCodeErrorInfo: ErrorInfo;
PickZipCodeErrorInfo: ErrorInfo;
begin
if Rec."Post Code" = '' then begin
InvalidPostCodeErrorInfo.Title := 'Post Code is not valid';
InvalidPostCodeErrorInfo.Message :=
StrSubstNo('You cannot leave post code empty');
InvalidPostCodeErrorInfo.RecordId := Rec.RecordId;
if CityHasUniquePostCode(Rec) then begin
InvalidPostCodeErrorInfo.AddAction(
StrSubstNo('Set value to %1', GetPostCode(Rec)),
Codeunit::ExtensionErrorManagement,
'FixPostCode'
);
Error(InvalidPostCodeErrorInfo)
end else begin
InvalidPostCodeErrorInfo.AddAction(
StrSubstNo('Show Post Codes for %1', Rec.City),
Codeunit::ExtensionErrorManagement,
'ShowPostCodes'
);
Error(InvalidPostCodeErrorInfo);
end;
end;
....
procedure FixPostCode(var ErrorInfo: ErrorInfo)
var
Cust: Record Customer;
begin
if Cust.Get(ErrorInfo.RecordId) then begin
Cust."Post Code" := GetPostCode(Cust);
Cust.Modify();
end;
end;
Use Case 3
Maybe the City has more than one postal code and we want the user to pick one of them.

Look at the bolded text which is also a show it and a fix it at the same time. I show the list of possible postal codes and allow the user to pick one.:
false, false)]
local procedure OnAfterValidatePostCode(CurrFieldNo: Integer; var Rec: Record Customer; var xRec: Record Customer)
var
PostCode: Record "Post Code";
ZipCode: Code[10];
InvalidPostCodeErrorInfo: ErrorInfo;
PickZipCodeErrorInfo: ErrorInfo;
begin
if Rec."Post Code" = '' then begin
InvalidPostCodeErrorInfo.Title := 'Post Code is not valid';
InvalidPostCodeErrorInfo.Message :=
StrSubstNo('You cannot leave post code empty');
InvalidPostCodeErrorInfo.RecordId := Rec.RecordId;
if CityHasUniquePostCode(Rec) then begin
InvalidPostCodeErrorInfo.AddAction(
StrSubstNo('Set value to %1', GetPostCode(Rec)),
Codeunit::ExtensionErrorManagement,
'FixPostCode'
);
Error(InvalidPostCodeErrorInfo)
end else begin
InvalidPostCodeErrorInfo.AddAction(
StrSubstNo('Show Post Codes for %1', Rec.City),
Codeunit::ExtensionErrorManagement,
'ShowPostCodes'
);
Error(InvalidPostCodeErrorInfo);
end;
end;
....
procedure ShowPostCodes(var ErrorInfo: ErrorInfo)
var
Cust: Record Customer;
PostCode: Record "Post Code";
PagePostCodes: Page "Post Codes";
begin
if Cust.Get(ErrorInfo.RecordId) then begin
PostCode.SetRange(City, Cust.City);
PagePostCodes.SetTableView(PostCode);
PagePostCodes.LookupMode := true;
if PagePostCodes.RunModal() = Action::LookupOK then begin
PagePostCodes.GetRecord(PostCode);
Cust."Post Code" := PostCode.Code;
Cust.Modify();
end;
end;
end;
If you want to see the entire extension, check my repository here:
SilviuVirlan/Actionable-Errors (github.com)
Microsoft documentation: Actionable errors – Business Central | Microsoft Learn
Lastly, an Actionable errors demo Youtube video is below:


One Response