AL runtime errors in Business Central
By Emil Björk · Microsoft business apps consultant, Gothenburg
The Business Central runtime errors AL developers and admins meet most — record already exists, does not exist, modified by another user, string length, locks and deadlocks, G/L inconsistency — with fixes.
Runtime errors are the ones users see: a red banner in the client, a failed job queue entry, a 400 from the API. Business Central's messages are unusually explicit about which table and which key is involved, so most of them can be diagnosed from the text alone. This reference covers the recurring ones in the order they show up in a typical tenant's telemetry: data errors, concurrency and locking, posting consistency, and the platform limits. Compile-time problems are in AL compiler errors.
Record errors
"The record in table X already exists. Identification fields and values: …"
Symptom. An insert fails and names the table and key.
Cause. A primary-key collision. The code calls Insert without checking existence; a number series is set to allow manual numbers and a user typed a duplicate; an integration re-sends a record it already created; or a key is composed from user input that is not unique.
Fix. Guard the insert: if not Rec.Get(Key) then Rec.Insert(true) else Rec.Modify(true), or use Rec.Insert(true, true) patterns where the platform handles it. For integrations, make the operation idempotent — look up by external ID first.
Prevention. Treat every insert in integration code as an upsert; see idempotency in Dynamics 365 integrations.
"The X does not exist. Identification fields and values: …"
Symptom. A Get fails, typically deep in a posting routine or report.
Cause. A lookup to a related record that has been deleted or was never created: a customer whose posting group was removed, an item referenced by a document line, a dimension value renamed. Also caused by code that calls Get on a blank key because a field was empty.
Fix. Read the identification fields in the message — they tell you exactly which key is missing — and either recreate the referenced record or fix the referring one. In code, use if Rec.Get(...) then where absence is legitimate, and TestField before the lookup where it is not.
Prevention. Do not delete setup records that have been used; block them instead. Validate references at entry time, not posting time.
"Another user has modified the record for this X after you retrieved it from the database."
Symptom. A Modify fails on a record the session read earlier.
Cause. Optimistic concurrency. Business Central stamps every row with a version; if the version in the database is newer than the one your session holds, the write is refused. Long-running pages, integrations that read a batch and write later, and job queue entries overlapping with user edits all trigger it.
Fix. Re-read immediately before writing (Rec.Get(Rec.RecordId) or Rec.Find), then Modify. In integration code, retry the read-modify-write once on this specific error text.
Prevention. Keep the gap between read and write short; never hold a record across a user prompt; give background processes their own change windows.
"The length of the string is X, but it must be less than or equal to Y characters. Value: …"
Symptom. An assignment into a Code or Text field fails at runtime.
Cause. Data longer than the field: an external system's 100-character name into a 50-character field, a concatenated key, an API payload. Older versions phrase this as "Overflow under type conversion of Text to Code".
Fix. Truncate deliberately with CopyStr(Value, 1, MaxStrLen(Rec.Field)), or widen the field in a table extension if the data legitimately needs it — but note that base-application fields cannot be widened.
Prevention. MaxStrLen on every assignment from external data; validate lengths at the integration boundary. The compiler warns about this pattern as AL0603.
"X must have a value in Y: Z. It cannot be zero or empty."
Symptom. A TestField fails, naming field, table, and record.
Cause. Setup is incomplete — a posting group without an account, a customer without a payment term — or the code tests a field the user has no way to fill.
Fix. Fill the named field on the named record. For posting-group and setup fields, Business Central posting setup errors lists which table holds what.
Prevention. Configuration checklists per company; the Company Hub and setup wizards catch most gaps.
"The filter 'X' is not valid for the Y field on the Z table."
Symptom. A SetFilter or user-entered filter fails.
Cause. Filter syntax applied to the wrong type — text operators on a date, an unescaped special character (&, |, @, *) in a value, or a Code filter with characters the field cannot hold.
Fix. Use SetRange for exact values, and for SetFilter escape values with '%1' placeholders and StrSubstNo, or wrap them in quotes via Rec.FieldName filter tokens.
Prevention. Never concatenate user or external data into a filter string.
Locking and concurrency
"The operation could not complete because a record was locked by another user. Please retry the activity."
Symptom. A write waits and then fails; in the client it appears after a pause of tens of seconds.
Cause. Another session holds a lock on the row or table for longer than the lock timeout — a long posting, a report with LockTable, a job queue entry processing a large batch, or an integration holding a transaction open across an external call.
Fix. Find the blocking session in the admin centre or via telemetry (lock timeout events name the blocking object and user), let it finish or cancel it, retry. In code, shorten the transaction: commit at safe points, move external calls outside the lock.
Prevention. Never call an external API inside a transaction that holds locks; schedule heavy batch work outside business hours; use ReadIsolation to avoid unnecessary locks on reads. Business Central performance tuning covers the patterns.
"Your activity was deadlocked with another user's activity. Please retry the activity."
Symptom. A write fails immediately with the deadlock message.
Cause. Two sessions each hold a lock the other needs — classically two posting routines touching the same tables in a different order, or a job queue entry and a user both updating an item and its ledger.
Fix. Retry; the platform chose your session as the victim. Then find the pair: telemetry's deadlock events include both statements.
Prevention. Lock tables in a consistent order in custom code (LockTable on the parent before the child), and serialise batch jobs that touch the same tables.
Posting consistency
"The transaction cannot be completed because it will cause inconsistencies in the G/L Entry table."
Symptom. A posting fails after all the validation passed, with no field named.
Cause. The consistency check at the end of Gen. Jnl.-Post Line found debits and credits in the transaction do not net to zero — a rounding difference from a custom posting or an event subscriber that adjusted one side, an inconsistent currency rounding setup, or a VAT rounding precision that differs between amount and base.
Fix. Debug the posting with a breakpoint on the consistency check, or post the document with the debugger attached and compare G/L entries in the buffer by posting group. The difference is usually cents; the offending line is the one whose amount was touched by code outside the standard routine.
Prevention. Subscribers on posting events must never change amounts without also adjusting the balancing entry; use the OnAfter… events to add entries, not to alter existing ones. Review currency and VAT rounding settings when a localisation is introduced.
"Attempted to divide by zero." / "Arithmetic operation resulted in an overflow."
Symptom. A calculation fails in a report or codeunit.
Cause. A quantity or rate of zero used as a divisor — typically unit cost per quantity where quantity is zero on a cancelled line — or a Decimal beyond its 18-digit range, or an Integer beyond 2^31.
Fix. Guard the division; use BigInteger or Decimal where sums can exceed integer range.
Prevention. Assume every divisor can be zero on real data.
Permissions and platform limits
"You do not have the following permissions on TableData X: Read / Insert / Modify / Delete"
Symptom. A user or the API caller is refused on a table they can see in the UI.
Cause. The permission set lacks direct or indirect permission for that table in that operation. Posting routines need indirect permissions on ledger tables through codeunit execution; a role built from BASIC alone lacks them. Also common after an extension adds a table without shipping a permission set.
Fix. Use the Effective Permissions page from the user card to see which set grants what; add the missing permission to a copied set, or assign the extension's permission set.
Prevention. Every extension ships a permission set object; assign by role, not by user. See Business Central permissions and security.
"The request was blocked because … exceeded the limit" / operational limits
Symptom. A session, job, or API call is terminated by the platform: too many rows in a report, a transaction running too long, too many sessions, too many API requests.
Cause. Business Central online enforces operational limits — maximum transaction duration, report row limits, concurrent sessions, API rate limits — that on-premises never had.
Fix. Split the work into smaller transactions or job queue entries; page API calls and honour Retry-After on 429s; reduce report scope.
Prevention. Read Microsoft's operational limits page for the current numbers and design batch work around them from the start. The API-specific errors are in Business Central API errors.
Finding the error in the first place
Enable telemetry to Application Insights in the admin centre: every runtime error is logged with the AL stack trace, the object, the user, and the SQL statement for lock and deadlock events. It turns "a user got an error yesterday" into a query. Business Central telemetry and monitoring covers the setup, and the debugger guide covers reproducing the error with snapshot debugging when the message alone is not enough.
Frequently asked questions
What does 'The record in table X already exists' mean?
- An Insert hit a primary-key collision — a record with that key is already there. Either the code inserts without checking (use Insert(true) after a Get or Find, or Insert then Modify), or a number series handed out a number that was already used, or the key is being built from user input that is not unique.
How do I fix 'Another user has modified the record for this X after you retrieved it from the database'?
- It is optimistic concurrency: your copy of the record is older than the database version. Re-read the record (Get or Find) immediately before Modify, keep transactions short, and in integrations retry the read-modify-write once on this specific error.
What causes 'The transaction cannot be completed because it will cause inconsistencies in the G/L Entry table'?
- The posting routine's consistency check found the G/L entries in the transaction do not balance to zero — usually a rounding difference from a custom posting routine, a currency or VAT rounding setting, or an event subscriber that changed an amount on one side. Check the amounts by posting group and dimension set in the debugger.
What is the difference between a lock error and a deadlock?
- 'The operation could not complete because a record was locked by another user' is a plain wait that timed out; 'Your activity was deadlocked with another user's activity' is two sessions each holding a lock the other needs, and the platform killed one. Both are fixed by shorter transactions, consistent lock order, and moving heavy work to the job queue.
Further reading
Related guides
- AL compiler errors in Business CentralThe AL compiler errors every Business Central developer hits — AL0118, AL0132, AL0185, AL0296, AL0432, AL0603, AL0604, ID-range and symbol errors — with cause, fix, and prevention.
- Business Central API errorsBusiness Central API and OData errors decoded — Authentication_InvalidCredentials, BadRequest_ResourceNotFound, Internal_CompanyNotFound, Request_EntityChanged, Application_DialogException, 429 limits, custom API 404s.
- Business Central job queue errorsWhy Business Central job queue entries fail or stall — Error status, stuck In Process, entries that never run, permission and user problems, overlapping jobs, sandbox copies, reports needing parameters — with fixes.
- Business Central journal and document posting errorsBusiness Central posting errors that are not posting groups — allowed posting dates, dimension code mandatory, number series, blocked customers and items, nothing to post, warehouse handling, approvals.
- Business Central posting setup errorsThe Business Central posting group errors — Gen. Posting Setup, VAT Posting Setup, Customer and Vendor Posting Group, Inventory Posting Setup, Direct Posting, blocked accounts — with cause, fix, prevention.
Browse every guide in Business Central or just Troubleshooting.
Spot something wrong or want a topic covered? Send a correction or a topic request — both are welcome.