Unused permission declared (AC0032)

The Permissions property should declare only the table data access the object actually uses. Entries that grant access to tables never read or written inside the object are dead code. Overly broad permission chars (rimd when only r is needed) grant more access than the runtime requires, which undermines the principle of least privilege.

This rule is the inverse of AC0031 . Where AC0031 detects missing permissions, AC0032 detects permissions that are declared but not backed by any code.

A code fix is available for this diagnostic.

Entire entry unused

When a Permissions entry references a table that no code in the object accesses at all:

codeunit 50100 "Post Sales Invoice"
{
    Permissions = tabledata "Sales Header" = rimd;

    procedure Post()
    begin
        // No code accesses "Sales Header"
    end;
}
Permission 'tabledata Sales Header' is declared but no code in this object accesses table 'Sales Header'. [AC0032]

Remove the unused entry:

codeunit 50100 "Post Sales Invoice"
{
    procedure Post()
    begin
    end;
}

Partial chars unused

When the declared permission chars exceed what the code actually needs:

codeunit 50100 "Post Sales Invoice"
{
    Permissions = tabledata "Sales Header" = rimd;

    procedure Post()
    var
        SalesHeader: Record "Sales Header";
    begin
        SalesHeader.FindFirst();
    end;
}
Permission 'imd' on 'tabledata Sales Header' is not needed. Only 'r' is required. [AC0032]

Reduce the permission to match actual usage:

codeunit 50100 "Post Sales Invoice"
{
    Permissions = tabledata "Sales Header" = r;

    procedure Post()
    var
        SalesHeader: Record "Sales Header";
    begin
        SalesHeader.FindFirst();
    end;
}

When the rule does not trigger

The diagnostic is suppressed when any of the following conditions apply:

  • The record variable is marked as Temporary
  • The target table is a system table (ID > 2,000,000,000)
  • The containing symbol is obsolete
  • The codeunit is a test codeunit with TestPermissions = Disabled
  • The containing object is a permissionset or permissionsetextension (these declare permissions structurally, not for access control)

Code fix

The ALCops: Remove unused permission code fix handles both variants:

  • Entire entry unused: removes the entry from the list. If it is the last entry, the entire Permissions property is removed.
  • Partial chars unused: reduces the permission string to only the chars that are actually used, in canonical rimd order.

See also