Don’t just tell me what’s wrong, help me instead in Business Central

In Dynamics 365 Business Central, we are really good at telling the users what they are doing wrong. But we’re not very good at telling them how to do something right or guide them in the right direction. In this video, I discuss examples and show what I’m doing to improve our apps to make them friendlier.

https://youtu.be/3KrXJwIkf8w

We’ve all been there — staring at a cryptic error message in Business Central that tells us exactly what’s wrong but offers zero guidance on how to fix it. In this video, Erik tackles a topic that’s been top of mind for him: making error messages actually helpful. He demonstrates the problem with a classic posting date error, shows how he’s improving error messages in his own SharePoint Connector app, and explores the powerful ErrorInfo data type that lets developers attach actionable buttons and navigation links directly to error dialogs.

The Problem: Errors That Don’t Help

Erik opens with a familiar scenario. You try to post a general journal in Business Central and you’re greeted with:

“Posting date is not within your range of allowed posting dates in General Journal Line, Journal Template Name: General, Journal Batch Name: Default, Line Number: 10000.”

The error is precise — it tells you exactly what’s wrong. But it offers not a single piece of advice on how to fix it. Where do you go? What do you change?

As Erik demonstrates, the posting date restriction could come from User Setup or from the General Ledger Setup. The error message doesn’t distinguish between them. A user unfamiliar with Business Central has to know that “User Setup” exists (which is different from “Users” — already confusing), navigate there, check the posting date range, potentially clear it, only to discover the restriction also exists in General Ledger Setup. The error gives you no clue which setup is responsible — it just says “you’re wrong” and leaves you on your own.

A Better Approach: Validate and Guide

Erik uses his own SharePoint Connector app as a case study. The app connects SharePoint folders to Business Central data across every table, but its flexible setup creates room for common configuration mistakes — particularly around the Azure app registration fields.

Validating the Client ID

When setting up the SharePoint Connector, users need to copy a Client ID (a GUID) and a Client Secret (a random string) from the Azure portal. Microsoft uses inconsistent terminology — sometimes it’s called “Application ID,” sometimes “Application Client ID” — which leads to users copying the wrong value into the wrong field.

Erik created a simple try function that checks whether a given string is a valid GUID:

Since it’s a try function, it won’t throw an error — it simply returns false if the string can’t be assigned to a GUID variable. This enables soft validation: the user is allowed to enter whatever they want (in case OAuth formats change in the future), but if the value doesn’t look like a GUID, the app proactively tells them:

“This doesn’t look right. The Client ID should be a GUID. You might have copied the wrong value from the Azure portal — look for ‘Application (client) ID’.”

Catching the Secret ID vs. Secret Value Mix-Up

The most common setup mistake — affecting roughly 80% of failed configurations — is users copying the Secret ID instead of the Secret Value. The Secret ID looks like a GUID, just like the Client ID, making it a very easy mistake to make.

Erik uses the same GUID-checking function in reverse: if the Client Secret field does contain a valid GUID, something is probably wrong, because the actual secret value should be a random string of characters, not a GUID. The app then displays:

“This doesn’t look right. The Client Secret should be a string of random characters. You might have copied the Secret ID and not the Secret Value from Azure — look for ‘Value’, not ‘Secret ID’.”

Validating the Callback URL

Another common setup issue involves the callback URL. The auto-generated URL only works for cloud environments, so on-premises users need to fine-tune it. However, the URL must always contain a specific page reference (e.g., page=70319501). If that piece is missing, Erik’s code knows for certain the URL is invalid and tells the user exactly what to append.

ErrorInfo: The Technical Foundation for Helpful Errors

Beyond better validation messages, Business Central’s ErrorInfo data type (available from runtime 11.0 / BC 22+) provides a powerful mechanism for attaching actionable fixes directly to error dialogs. The source code Erik shares demonstrates this beautifully:

pageextension 50100 CustomerListExt extends "Customer Card"
{
    actions
    {
        addfirst(processing)
        {
            action(Test)
            {
                ApplicationArea = All;
                Caption = 'Test';
                Image = Test;
                Promoted = true;
                PromotedCategory = Process;
                PromotedIsBig = true;
                ToolTip = 'Test';

                trigger OnAction()
                var
                    e: ErrorInfo;
                    Helpful: Codeunit Helpful;
                begin
                    e.Message := 'Not that fancy';
                    e.PageNo := 21;
                    e.FieldNo := Rec.FieldNo(Address);
                    e.RecordId := Rec.RecordId;
                    e.AddNavigationAction('Go North');
                    e.AddAction('Go South', 50100, 'Behelpful');
                    Helpful.SetContext(Rec.SystemId);
                    error(e);
                end;
            }
        }
    }
}

Let’s break down what’s happening here:

  • e.Message — Sets the error message text the user sees.
  • e.PageNo and e.FieldNo — Tell the system which page and field are relevant, giving the error context.
  • e.RecordId — Ties the error to a specific record.
  • e.AddNavigationAction('Go North') — Adds a button to the error dialog that navigates the user to the relevant page and field — essentially a “Go here to fix it” link.
  • e.AddAction('Go South', 50100, 'Behelpful') — Adds a custom action button that calls a specific procedure in a codeunit, enabling the app to do something to help resolve the issue programmatically.

The supporting codeunit shows how context is preserved using SingleInstance and a stored SystemId:

codeunit 50100 "Helpful"
{
    SingleInstance = true;

    procedure Behelpful(e: ErrorInfo)
    var
        C: Record Customer;
    begin
        C.GetBySystemId(RememberedSystemId);
        message('Wasn''t that helpful? %1', C.Name);
    end;

    procedure SetContext(g: Guid)
    begin
        RememberedSystemId := g;
    end;

    var
        RememberedSystemId: Guid;
}

The SetContext procedure stores the current record’s SystemId before the error is raised. When the user clicks the “Go South” action button on the error dialog, Behelpful is invoked, retrieves the customer record, and can take corrective action or provide additional guidance. This pattern — using a SingleInstance codeunit to carry context into an error action handler — is a practical technique for building truly interactive error experiences.

Notifications vs. Errors vs. Messages

Erik also considers the delivery mechanism for these helpful messages. He’s currently using Message for soft validations (like the GUID checks), which allows users to proceed even if something looks wrong. However, he’s considering other options:

  • Notifications — Non-intrusive banners at the top of the page. The downside? Users have become “notification blind” due to an overabundance of irrelevant notifications in the base application.
  • Messages — Dialog boxes that require acknowledgment. Users see them but can dismiss and continue.
  • Errors with actions — The ErrorInfo approach shown in the code, which blocks the user but gives them actionable buttons to resolve the issue right from the error dialog.

A Call to Action for the Ecosystem

Erik emphasizes that this isn’t a rant — it’s a self-improvement exercise. He acknowledges that Microsoft’s base app, his own apps, and the broader ecosystem all share this problem. The classic TestField pattern is perhaps the worst offender: “This field cannot be blank” — but what should go in it? Where does the value come from? Who configures it?

His key takeaways for Business Central developers:

  1. Don’t just tell users what’s wrong — tell them how to fix it.
  2. Anticipate common mistakes and validate proactively with helpful guidance.
  3. Use ErrorInfo to add navigation actions and custom fix-it actions to your error messages.
  4. Include links or page references so users can go directly to where the fix needs to happen.
  5. Consider your audience — new users especially benefit from friendlier, more descriptive error handling.

Conclusion

Better error messages aren’t just a nice-to-have — they’re a fundamental part of good software design. Business Central gives developers the tools (like ErrorInfo with navigation and custom actions) to build genuinely helpful error experiences. The challenge is taking the time to think about what the user needs to hear, not just what the system knows is wrong. By validating inputs with context-aware guidance, using actionable error dialogs, and anticipating common mistakes, we can make the entire Business Central ecosystem more approachable — one error message at a time.