← All postsDevelopment ยท 3 November 2026

Field types, field lengths and overflow errors: getting the data model right the first time

Text[250] for a field that will never hold more than 20 characters is not harmless. Every table has a record size budget as well as a column budget, and every mismatch between a source field and a target field is a future "the length of the string is X, but it must be less than or equal to Y" at posting time. How to choose types and lengths, how record size actually works, and the patterns that stop overflow errors before they reach a user.

Two habits account for most of the data-model trouble we find in per-tenant extensions. The first is Text[250] on every text field, because it was the old default and nobody thought about it. The second is copying a value from one field to another without checking the two fields are the same size. The first quietly eats a budget that the table cannot get back. The second produces one of the most common runtime errors in Business Central, usually at posting time, usually in front of a user. Both are avoidable at design time, and this is how.

Choose the type for what the data is

TypeUse it forNot for
Code[n]Identifiers and keys: numbers, codes, references. Stored upper-case, trimmed, sorted as a key. Primary keys are almost always Code.Free text (it will be upper-cased), anything with meaningful case or leading spaces
Text[n]Descriptions, names, addresses, notes up to a sensible limit. Case preserved.Identifiers you will filter or join on (use Code); long documents (use Blob or Media)
Integer / BigIntegerCounts, sequence numbers (Entry No. is Integer; use BigInteger only when you will genuinely exceed 2.1 billion)Money or quantities (no decimals)
DecimalAmounts, quantities, prices, percentages. Set DecimalPlaces and AutoFormatType so it displays as the base application does.Identifiers
Date, Time, DateTimeDate for business dates (posting, due, shipment); DateTime for timestamps (when something happened, in UTC); Time rarely on its own. Duration for elapsed time.Storing a date as text, ever
BooleanYes/no states. Name as a state ("Requires Pallet").Three-state things (use an Enum with a blank value)
EnumAny fixed list of named values. Extensible by other apps.Option, which is the legacy type and should not be used in new code
GuidCross-system identifiers, correlation IDsHuman-facing numbers
Blob, Media, MediaSetLong text (Blob with a Text getter/setter), files, images. Stored out of the row; only loaded when asked for.Anything you need to filter or display in a list
RecordId, TableFilterReferences to arbitrary records; stored filters (setup tables)Ordinary foreign keys (use Code with a TableRelation)

Two habits that follow: set TableRelation on every Code field that references another table, so lookups and validation come free; and never store a number, date or amount as text because "it is just for display". Someone will filter on it.

Choose the length for what the data is

The question is "what is the longest value this field will ever legitimately hold?", not "what is the biggest number I can type". A postcode is 10. A company registration number is 20. A customer's name in the base application is Text[100]; an address line is Text[100]; a description is Text[100]; a document number is Code[20]; a dimension value is Code[20]. If your field holds the same kind of thing as a base field, use the base field's length, and name it the same way, so that values can move between them without truncation.

The reason this matters is that the length is not free. The table has two budgets:

So: Text[20] if the longest value is 20. You can widen a field later without losing data (widening is an additive schema change); you cannot narrow one that has data in it without the obsolete-and-migrate dance. Start small and widen when the business proves it needs to.

Overflow errors: where they come from

"The length of the string is 37, but it must be less than or equal to 30 characters. Value: ..." is the platform refusing to put a longer value into a shorter field. It is a runtime error, it rolls back the transaction, and it happens exactly when a value crosses from one field into another: in a posting routine copying header to ledger, in TransferFields, in an integration mapping an API payload, in a report assembling a column, in a validate trigger building a description. The numeric version ("Overflow under type conversion of Integer to ...") is the same idea for numbers that do not fit the target type.

The root cause is always the same: the source field is longer than the target field, and nothing checked. The fix is never to widen the target to 250 and move on. It is to make the sizes agree, or to handle the difference explicitly.

The patterns that prevent them

Reviewing an existing extension

Three quick checks that find most of it. List every text and code field with its length; anything at 250 or 2048 that holds a short value is a candidate to narrow at the next schema change. Grep for := between two different record types' text fields and for TransferFields, and compare lengths on each side. And search the telemetry for the overflow error text (it is logged like any other error, see the telemetry post); the ones users are hitting are already there.

The rule in one line

Type for what the data is, length for the longest legitimate value, the same field the same size everywhere it flows, and CopyStr with MaxStrLen at every boundary where that is not true. It is five minutes of thought per field at design time and it removes a whole category of production errors. It is also one of the first things the AL code check looks at, because it is one of the easiest things to get right.

Talk to us
Want this done in your Business Central?
Book a 30 minute callGet the monthly newsletter

More from the blog