Skip to content

AA0136 does not flag unreachable code after Record.FieldError(...), although it does after Error(...) #8324

Description

1. Describe the bug

CodeCop rule AA0136 (Do not write code that will never be hit) detects unreachable code after a built-in Error(...) call, but not after Record.FieldError(...) or FieldRef.FieldError(...), even though both unconditionally stop the execution of AL code.

The official documentation describes both methods with the same terminal semantics:

  • Dialog.Error: "Displays an error message and ends the execution of AL code."
  • Record.FieldError / FieldRef.FieldError: "Stops the execution of the code, causing a run-time error, and creates an error message for a field."

Since FieldError is the idiomatic way to raise a field-specific validation error, dead code following it goes undetected, while the semantically identical Error(...) pattern is flagged.

2. To Reproduce

Steps to reproduce the behavior:

  1. Create an AL project with CodeCop enabled ("al.codeAnalyzers": ["${CodeCop}"]).
  2. Add the codeunit below and observe the AA0136 diagnostics.
codeunit 50100 "AA0136 FieldError Repro"
{
    local procedure DemoUnreachable(SalesLine: Record "Sales Line")
    begin
        SalesLine.FieldError(Type);
        Message('Unreachable'); // NOT flagged by AA0136 - but this code can never run

        Error('Stop');
        Message('Unreachable'); // IS flagged by AA0136
    end;
}

3. Expected behavior

AA0136 is reported on both Message(...) statements: a statement directly following an unconditional FieldError(...) call can never be hit, exactly like one following Error(...).

4. Actual behavior

AA0136 is reported only on the statement following Error(...). The statement following SalesLine.FieldError(Type) produces no diagnostic.

Additional analysis: the rule's unreachable-after-throw detection matches an expression statement whose target method is named error and whose containing symbol is a built-in language class symbol. That second condition already holds for FieldError ΓÇö its containers (the Table and FieldRef language classes) are built-in class symbols, exactly like Dialog for Error. Only the literal name comparison excludes it, so extending the check to also accept FieldError (all four overloads: Record.FieldError(Field[, Text]), Record.FieldError(Field, ErrorInfo), FieldRef.FieldError([Text]), FieldRef.FieldError(ErrorInfo)) would be consistent with the existing design. TestField should not be added, as it only errors conditionally.

Found while investigating the inverse gap in a third-party analyzer: ALCops/Analyzers#463.

5. Versions:

  • AL Language: 18.0.2668733
  • Visual Studio Code: 1.134.0 (commit 110a328ea54b42367b803ec53ee0bf52ef26b419)
  • Business Central: N/A (compile-time CodeCop diagnostic; no server involved)
  • List of Visual Studio Code extensions that you have installed: AL Language extension only (all other extensions disabled while reproducing)
  • Operating System:
    • Windows
    • Linux
    • MacOS

Final Checklist

Please remember to do the following:

  • Search the issue repository to ensure you are reporting a new issue

  • Reproduce the issue after disabling all extensions except the AL Language extension

  • Simplify your code around the issue to better isolate the problem


Generated with Claude Fable 5

Internal work item: AB#647929

Metadata

Metadata

Assignees

No one assigned

    Labels

    CodeCopThis is a specific static-code-analysis group (AA)accepted

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions