title | description | ms.custom | ms.date | ms.reviewer | ms.topic | author | ms.author |
---|---|---|---|---|---|---|---|
Actionable errors |
Learn how to write AL code that returns error dialogs where users might unblock themselves. |
bap-template |
12/21/2023 |
jswymer |
conceptual |
samirdal |
samirdal |
This article describes how to handle error dialogs in AL code, specifically how to use the error handling framework to provide recommended actions to users to resolve errors more effectively.
For advice on how to design error dialogs that users understand, see User experience guidelines for errors.
[!INCLUDE actionable-errors-overview]
[!INCLUDE actionable-errors-fix-it-actions]
To achieve consistency in the user experience of Fix-it actions, consider following these guidelines for button labels:
[!INCLUDE fix-it-button-guidance]
The following AL code illustrates how to set up an error dialog with a Fix-it action.
var
dimension: Text[30];
vendorCode: Text[30];
FixitErrorInfo: ErrorInfo;
begin
// setup the error info object
FixitErrorInfo.Title('The line dimension value isn''t valid');
FixitErrorInfo.Message(
StrSubstNo('The dimension value must be blank for the dimension %1 for Vendor %2', dimension, vendorCode)
);
FixitErrorInfo.DetailedMessage('Add some text to help the person troubleshooting this error.');
FixitErrorInfo.AddAction(
'Set value to blank',
Codeunit::FixitCodeunit,
FixitCodeunitMethodName
);
Error(FixitErrorInfo);
end
If the user experience the error they see the following error dialog
:::image type="content" source="media/error-dialog-fixit.png" alt-text="Error dialog with fix-it action":::
The following AL code illustrates how to set up field validation with a Fix-it action.
...
field(17; "Qty. to Invoice"; Decimal)
{
// maybe some field properties
trigger OnValidate()
var
CannotInvoiceErrorInfo: ErrorInfo;
CheckField: Boolean;
begin
// some calculations here
CheckField := // calculate if true or false
if (CheckField)
then begin
// setup the error info object
CannotInvoiceErrorInfo.Title := 'Qty. to Invoice isn''t valid';
CannotInvoiceErrorInfo.Message :=
StrSubstNo('You cannot invoice more than %1 units.', MaxQtyToInvoice());
CannotInvoiceErrorInfo.DetailedMessage('Add some text to help the person troubleshooting this error.');
CannotInvoiceErrorInfo.RecordId := Rec.RecordId;
CannotInvoiceErrorInfo.AddAction(
StrSubstNo('Set value to %1', MaxQtyToInvoice()),
Codeunit::FixitCodeunit,
FixitCodeunitMethodName
);
Error(CannotInvoiceErrorInfo);
end;
// maybe more validation logic here
end;
}
...
If the user experience that the field can't be validated, they see the following dialog
:::image type="content" source="media/validation-error-fixit.png" alt-text="Validation error with fix-it action":::
[!INCLUDE actionable-errors-show-it-actions]
To achieve consistency in the user experience of Show-it actions, consider following these guidelines for button labels:
[!INCLUDE show-it-button-guidance]
The following AL code illustrates how to set up an error dialog with a Show-it action.
procedure ShowShipmentDialog()
var
ErrorNoLinesToCreate: ErrorInfo;
SomeCheckCondition: Boolean;
begin
// some business logic
SomeCheckCondition := // calculate if true or false
if (SomeCheckCondition)
begin
// maybe some business logic here
// setup the error info object
ErrorNoLinesToCreate.Title := 'There are no new warehouse shipment lines to create';
ErrorNoLinesToCreate.Message := 'This usually happens when warehouse shipment lines [...]';
ErrorNoLinesToCreate.DetailedMessage('Add some text to help the person troubleshooting this error.');
ErrorNoLinesToCreate.PageNo := Page::"Warehouse Shipment List";
ErrorNoLinesToCreate.AddNavigationAction('Show open lines');,
Error(ErrorNoLinesToCreate);
// maybe more business logic here
end;
// some more business logic here
If the user experience the error they see the following error dialog
:::image type="content" source="media/error-dialog-showit.png" alt-text="Error dialog with show-it action":::
The following AL code illustrates how to set up a validation error dialog with a Show-it action.
...
field(59; "Gen. Prod. Posting Group"; Code[20])
{
// maybe some field properties
trigger OnValidate()
var
CheckIfFieldIsEmpty: Boolean;
FieldEmptyErrorInfo: ErrorInfo;
begin
CheckIfFieldIsEmpty := // calculate if true or false
if (CheckIfFieldIsEmpty)
then begin
// setup the error info object
FieldEmptyErrorInfo.Message :=
StrSubstNo('Gen. Prod. Posting Group must have a value in item: %1. It can''t be zero or empty.', ItemNo);
FieldEmptyErrorInfo.DetailedMessage('Add some text to help the person troubleshooting this error.');
CannotInvoiceErrorInfo.RecordId := ItemRec.RecordId;
CannotInvoiceErrorInfo.AddNavigationAction(
StrSubstNo('Show Item %1', ItemNo)
);
ChangeNotAllowedErrorInfo.PageNo(Page::"Item Card");
Error(CannotInvoiceErrorInfo);
end;
// maybe more validation logic here
end;
}
...
If the user experience that the field can't be validated, they see the following dialog
:::image type="content" source="media/validation-error-showit.png" alt-text="Validation error with show-it action":::
Error messages can have up to two recommended actions. In this section, we show some different examples of how to use multiple actions and why.
The following AL code illustrates how to set up an error dialog with two actions.
var
ErrorDialogWithTwoActions: ErrorInfo;
DimensionCode: Code[20];
VendorCode: Code[20];
begin
// set values for DimensionCode, VendorCode variables
// setup the error info object
ErrorDialogWithTwoActions.Title := 'The line dimension value isn''t valid';
ErrorDialogWithTwoActions.Message := StrSubstNo('The dimension value must be blank for the dimension %1 for Vendor %2', DimensionCode, VendorCode);
ErrorDialogWithTwoActions.DetailedMessage('Add some text to help the person troubleshooting this error.');
ErrorDialogWithTwoActions.AddAction(
'Set value to blank',
Codeunit::FirstFixitCodeunit,
"FirstFixitCodeunitMethodName"
);
ErrorDialogWithTwoActions.AddAction(
'OK',
Codeunit::SecondFixitCodeunit,
"SecondFixitCodeunitMethodName"
);
Error(ErrorDialogWithTwoActions);
end;
In this error dialog case, the recommended Fix-it action sets the value to blank, meaning that it clears out the field value.
Notice the error dialog has two actions. In error cases both buttons are styled equally as secondary buttons, to allow users to consider the most suitable way to get unblocked for their case.
If the user experience the error they see the following error dialog
:::image type="content" source="media/error-dialog-multiple.png" alt-text="Error dialog with multiple actions":::
The following AL code illustrates how to set up field validation with two actions.
field(4; "Account No."; Code[20])
{
// maybe some field properties
trigger OnValidate()
var
PendingApprovalErrorInfo: ErrorInfo;
begin
SomeCheckCondition := // calculate if true or false
if (SomeCheckCondition)
then begin
PendingApprovalErrorInfo.Message := 'You can''t modify a record pending approval. Add a comment or reject the approval to modify the record.';
PendingApprovalErrorInfo.DetailedMessage('Add some text to help the person troubleshooting this error.');
PendingApprovalErrorInfo.PageNo := Page::"Comments";
PendingApprovalErrorInfo.AddNavigationAction('Show comments');
PendingApprovalErrorInfo.AddAction(
'Reject approval'
Codeunit::SecondFixitCodeunit,
SecondFixitCodeunitMethodName
);
Error(PendingApprovalErrorInfo);
end;
end;
}
Here the Show-it action shows the related Comments table, and the Fix-it action rejects the approval.
Users can also get unblocked by refreshing the page or copying the error details for sharing and troubleshooting.
If the user experience that the field can't be validated, they see the following dialog
:::image type="content" source="media/validation-error-multiple.png" alt-text="Validation error with multiple actions":::
When there isn’t any known solution to recommend, the error dialog has one primary OK button. Users can copy and share the full error details needed for troubleshooting and support.
The following AL code illustrates how to set up an error dialog with no actions (which is also the standard behavior of the Error
method)
var
ErrorDialogNoActions: ErrorInfo;
begin
// setup the error info object
ErrorDialogNoActions.Title := 'The ''Starting Date'' isn''t valid';
ErrorDialogNoActions.Message := 'The ''Starting Date'' must be the first date of an accounting period. Try changing the date to first date of the month.';
ErrorDialogNoActions.DetailedMessage('Add some text to help the person troubleshooting this error.');
Error(ErrorDialogNoActions);
end;
If the user experience the error they see the following error dialog
:::image type="content" source="media/error-dialog-nosolution.png" alt-text="Error dialog with no solution":::
Failure modeling and robust coding practices
User experience guidelines for errors
Understanding the error dialog
Dialog.Error(ErrorInfo) Method
AL error handling