[Bug]: Error Message Management LogTestField misresolves enum captions on comma/ordinal gaps
Nobody has claimed this yet.
- Dominant language
- AL
- Stars
- 683
- Forks
- 459
- Avg merge
- 3d 26m
- Merged PRs (30d)
- 633
Description
Describe the issue
Codeunit 28 "Error Message Management".LogTestField(SourceVariant; SourceFieldNo; ExpectedValue) resolves the expected value's caption by position:
// ErrorMessageManagement.Codeunit.al, LogTestField(...; ExpectedValue: Variant)
if FldRef.Type() = FieldType::Option then begin
IntValue := ExpectedValue;
ExpectedValue := SelectStr(IntValue + 1, FldRef.OptionCaption());
end;
An enum field's FieldRef.Type() is Option, so this branch runs for enums too. IntValue is the expected value's ordinal, but OptionCaption for an enum is a comma-joined list that is dense over the defined values only, and any single caption may itself contain a comma. Indexing that list by ordinal + 1 is therefore wrong in two independent ways:
Ordinal gap -> runtime error. An enum with non-contiguous ordinals (e.g. 0,1,2,10) has an ordinal larger than the number of captions, so SelectStr is asked for an index past the end and throws. The collected-errors flow, whose purpose is to accumulate messages without throwing, crashes instead.
Comma in a caption -> wrong label. A caption such as 'Received, not invoiced' adds a comma to the list, shifting every later entry by one, so the rendered message names the wrong member.
The normal fallback path in the same method.. FldRef.TestField(ExpectedValue) when collection is inactive (and at line ~361) - renders the caption correctly via metadata, so a correct resolution already exists in the same procedure; only the collected-errors branch uses the positional lookup.
Expected behavior
LogTestField resolves the expected enum value's caption the same way TestField/Format do - via field/enum metadata - so it returns Omega and Received, not invoiced, and never throws.
Steps to reproduce
BC 27.1.41698.41776 (w1, OnPrem container). Minimal enum + a call through the collectible-errors API:
enum 50100 "Gap Enum"
{
value(0; Alpha) { Caption = 'Alpha'; }
value(1; Beta) { Caption = 'Beta'; }
value(2; CommaMember) { Caption = 'Received, not invoiced'; } // comma in caption
value(10; Omega) { Caption = 'Omega'; } // ordinal gap 2 -> 10
}
// table 50100 "Gap Rec" (temporary) with field(1; "Gap Value"; Enum "Gap Enum")
codeunit 50100 "Gap Repro"
{
trigger OnRun()
var
GapRec: Record "Gap Rec" temporary;
ErrorMessageMgt: Codeunit "Error Message Management";
ErrorMessageHandler: Codeunit "Error Message Handler";
ErrorContextElement: Codeunit "Error Context Element";
begin
GapRec.Init();
GapRec."Gap Value" := GapRec."Gap Value"::Alpha; // actual value differs from expected
GapRec.Insert();
ErrorMessageMgt.Activate(ErrorMessageHandler);
ErrorMessageMgt.PushContext(ErrorContextElement, GapRec, 0, '');
// ordinal 2, comma caption -> renders wrong label
ErrorMessageMgt.LogTestField(GapRec, GapRec.FieldNo("Gap Value"), GapRec."Gap Value"::CommaMember);
// ordinal 10, gap -> throws in SelectStr
ErrorMessageMgt.LogTestField(GapRec, GapRec.FieldNo("Gap Value"), GapRec."Gap Value"::Omega);
end;
}
Additional context
Found while testing enum caption resolution through the collectible-errors API. The attached repro is self-contained; no external app is required to reproduce.
Status: Error
Error: field OptionCaption SelectStr indexes into: "Alpha,Beta,Received, not invoiced,Omega"
correct captions: Alpha=ord0, Beta=ord1, "Received, not invoiced"=ord2, Omega=ord10
LogTestField expected=Omega (ord 10 -> SelectStr(11)): threw:
- The SELECTSTR comma-string Alpha,Beta,Received, not invoiced,Omega does not contain a value for index 11.
- LogTestField expected=CommaMember (ord 2 -> SelectStr(3)): logged (no throw)
- LogTestField expected=Beta (ord 1 -> SelectStr(2), control): logged (no throw)
== collected error messages ==
Message="Gap Value must be equal to Received."
Message="Gap Value must be equal to Beta."
I will provide a fix for a bug
- I will provide a fix for a bug
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in ErrorMessageManagement.Codeunit.al at LogTestField, focusing on the collected-errors branch and comparing it with the metadata-based fallback near line 361. Use the self-contained enum reproduction to verify captions containing commas and non-contiguous ordinals. Done means CommaMember reports “Received, not invoiced” and Omega logs without throwing.
Written by the indexing model from the issue text.
Assessment
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100