MB-820 common mistakes
MB-820 · Understand the traps and how to avoid them.
Assigning new table, page, or codeunit object IDs that fall outside the extension's declared idRanges, or forgetting to add an idRanges section to app.json.
Business Central object IDs are tenant-wide; the base app and other extensions already occupy many IDs. A collision causes deployment/synchronization failures or an object conflict that only appears in the target environment.
What to do instead
Declare a unique range in app.json (for example 50100-50199) and keep every new object inside it. Check existing ranges with the symbol reference or the customer's object ID report before allocating.
Publishing an extension without first downloading symbols for the selected environment, or leaving app.json application/platform versions that do not match the target tenant.
AL compiles against base app symbols. Missing or mismatched symbols produce object-not-found and dependency errors, so the .app cannot deploy.
What to do instead
Select the correct environment in VS Code, run AL: Download Symbols, set application and platform to the tenant versions, add dependencies on the Application and System apps, then build and publish.
Adding new table fields without a DataClassification property and then wondering why the extension will not compile.
The AL compiler enforces DataClassification on table fields in extensions for privacy and compliance. Omitting it is a hard compile error, not just a warning.
What to do instead
Set DataClassification on every new field, for example CustomerContent, EndUserIdentifiableInformation, or SystemMetadata, then rebuild.
Writing an event subscriber whose parameter list differs from the publisher (wrong parameter count, type, or order), or subscribing to an event that does not exist in the referenced dependency version.
AL binds subscribers to publishers by exact signature at compile time. A near-match either fails to compile or binds to a different publisher and never runs.
What to do instead
Copy the publisher signature exactly from the symbol or source, including Rec and xRec types, add the EventSubscriber attribute with the correct object type, ID, and event name, and verify the dependency version contains the publisher.
Calling Commit() inside a loop, inside an event subscriber, or in the middle of a multi-table update to save progress.
Commit ends the current transaction. A later error cannot roll back already-committed rows, which can leave inconsistent data and break codeunit and event transaction semantics.
What to do instead
Keep business logic transactional. Commit only at an explicit boundary such as a batch-job checkpoint, and handle errors with Codeunit.Run or if not ... then so the whole unit rolls back on failure.
Trying to assign a value to a FlowField, or defining a FlowField without a correct CalcFormula.
FlowFields are calculated at read time and are not stored. Assignment causes a runtime error, and a missing or incorrect CalcFormula returns wrong or empty values.
What to do instead
Define CalcFormula with the correct Sum, Count, Exist, or Lookup, table, field, and filter. Call CalcFields before reading and never write to the field.
Creating a PageType=API page without setting APIPublisher, APIGroup, APIVersion, EntityName, and EntitySetName, or sourcing it from a table without a primary key.
Business Central exposes only API pages that have the full API metadata. Missing properties make the page non-routable, and the endpoint returns 404 or 400.
What to do instead
Set all API properties on the page, use a table with a primary key, set ODataKeyFields and DelayedInsert where needed, then test the /api//// URL.
Hardcoding URLs and credentials in AL code and calling HttpClient without checking IsSuccessStatusCode or reading the response content.
Secrets in code leak through source control and extensions. A failed HTTP call then throws an unhelpful error or continues with empty data.
What to do instead
Store endpoints and secrets in a setup table, IsolatedStorage, or Key Vault using SecretText. Check if not Response.IsSuccessStatusCode then Error(...), read content with ReadAsStringAsync, and dispose the HttpResponseMessage.
Creating new tables, pages, and codeunits but not adding them to a permission set, or only testing as an administrator.
New objects are not automatically granted to users. Administrators bypass permissions in development, so the gap only appears for non-admin users in test or production.
What to do instead
Add tableData, page, and codeunit entries to a permission set or extend an existing one, assign it to a test user, and verify with a non-admin login.
Assuming you can modify base application objects directly or edit a per-tenant extension in the production tenant.
Business Central online is extensibility-only. The base app is locked, and published per-tenant extensions are read-only in production.
What to do instead
Use table and page extensions and events, develop and test in a sandbox, and deploy changes by publishing a new extension version instead of editing production objects.