Possible overflow assigning

Properties
PC0022 Warning Design Code Fix Ignore Obsolete

Microsoft’s AA0139 catches direct assignments from a larger Text or Code to a smaller target. This rule extends AA0139 to cover values that reach a field through Validate, SetFilter, or Get — and Labels whose translations can exceed the target length even when the source-language text fits.

In every case the runtime error is the same: The length of the string is X, but it must be less than or equal to Y characters.

Validate

When a procedure accepts a Code or Text parameter and passes it to Validate, the target field may be smaller. The runtime does not truncate — it throws.

procedure SetCustomerNo(InputNo: Code[50])
var
    Customer: Record Customer;
begin
    Customer.Validate("No.", InputNo); // Possible overflow assigning [PC0022]
end;

Wrap with CopyStr to fit the target field:

procedure SetCustomerNo(InputNo: Code[50])
var
    Customer: Record Customer;
begin
    Customer.Validate("No.", CopyStr(InputNo, 1, MaxStrLen(Customer."No.")));
end;

SetFilter

A method that returns Text (up to 2048 characters) or a variable larger than the filtered field can overflow the filter value:

procedure FilterCustomers()
var
    Customer: Record Customer;
begin
    Customer.SetFilter("No.", '%1', GetCustomerFilter()); // Possible overflow assigning [PC0022]
end;

Constrain the filter value before passing it:

procedure FilterCustomers()
var
    Customer: Record Customer;
begin
    Customer.SetFilter("No.", '%1', CopyStr(GetCustomerFilter(), 1, MaxStrLen(Customer."No.")));
end;

SetFilter with Labels

Labels used in filter expressions are a subtle variant. The English text may fit the field, but translators have no way to know the target field’s maximum length unless the Label carries a constraint. Even labels that should never be translated — filter expressions, tokens, format strings — trigger the diagnostic when they lack MaxLength or Locked:

procedure ExcludeDefaultCustomers()
var
    Customer: Record Customer;
    ExcludeFilterLbl: Label '<>10000&<>20000';
begin
    Customer.SetFilter("No.", ExcludeFilterLbl); // Possible overflow assigning [PC0022]
end;

For a label that must never change, add Locked = true. A locked label cannot be translated, so its compile-time length is final:

procedure ExcludeDefaultCustomers()
var
    Customer: Record Customer;
    ExcludeFilterLbl: Label '<>10000&<>20000', Locked = true;
begin
    Customer.SetFilter("No.", ExcludeFilterLbl);
end;

When the label is translatable, use MaxLength instead so translators see the limit:

procedure ExcludeDefaultCustomers()
var
    Customer: Record Customer;
    ExcludeFilterLbl: Label '<>10000&<>20000', MaxLength = 20;
begin
    Customer.SetFilter("No.", ExcludeFilterLbl);
end;

Text.StrSubstNo() method

Customer.SetFilter("No.", StrSubstNo('%1', ExcludeFilterLbl));

An other option would be to wrap this inside a Text.StrSubstNo() Method. The filter expression parameter isn’t a string literal text then anymore.

Get

String concatenation or StrSubstNo can produce a value longer than the primary key field:

procedure FindOrder(OrderNo: Code[20])
var
    SalesHeader: Record "Sales Header";
    PrefixTok: Label 'ORD-', Locked = true;
begin
    SalesHeader.Get(Enum::"Sales Document Type"::Order, PrefixTok + OrderNo); // Possible overflow assigning [PC0022]
end;

'ORD-' (4 characters) plus a full Code[20] value produces up to 24 characters — more than the "No." field allows. For lookup keys, silent truncation produces wrong lookups. Restructure the logic so the combined value fits the field by design, or wrap with CopyStr when truncation is acceptable:

procedure FindOrder(OrderNo: Code[20])
var
    SalesHeader: Record "Sales Header";
    PrefixTok: Label 'ORD-', Locked = true;
begin
    SalesHeader.Get(Enum::"Sales Document Type"::Order, CopyStr(PrefixTok + OrderNo, 1, 20));
end;

When the diagnostic is reported

  • A Label without MaxLength or Locked is assigned to a Text or Code variable, passed to Validate, used in SetFilter, or returned via exit.
  • A Text or Code variable is assigned to a smaller Text or Code target.
  • A StrSubstNo expression can produce a result longer than the target field.
  • An XmlPort textelement (implicit Text[1024]) flows into a shorter Code or Text field.

Labels with Locked = true or an explicit MaxLength that fits the target do not trigger the diagnostic.

Code fix

Two code fixes are available:

  • Wrap with CopyStr: wraps the value with CopyStr(value, 1, MaxStrLen(target)). When MaxStrLen is not available (e.g. in exit statements), the literal target length is used instead.
  • Add MaxLength to Label: adds MaxLength = N to the Label declaration, where N matches the target length. Only offered when the source is a Label.

See also