Table data access requires explicit object permissions
When a codeunit, report, query, or xmlport accesses table data without declaring the required permissions, the runtime relies on the calling user’s direct permissions. This breaks indirect permission scenarios, where a user’s license grants only indirect access to a table (for example, indirect write on ledger entry tables or indirect read on the Sent Emails table). Declaring Permissions = tabledata ... = rimd on the object allows the runtime to grant access through the object, regardless of the user’s direct license assignment.
Example
codeunit 50100 "Post Sales Invoice"
{
procedure Post()
var
SalesHeader: Record "Sales Header";
begin
SalesHeader.FindFirst(); // Table data access requires explicit object permissions [AC0031]
end;
}Add the Permissions property to the containing object:
codeunit 50100 "Post Sales Invoice"
{
Permissions = tabledata "Sales Header" = r;
procedure Post()
var
SalesHeader: Record "Sales Header";
begin
SalesHeader.FindFirst();
end;
}When the diagnostic is reported
The following record method calls trigger this diagnostic:
| Permission | Methods |
|---|---|
Read (r) | Find, FindFirst, FindLast, FindSet, Get, GetBySystemId, IsEmpty, Count |
Insert (i) | Insert |
Modify (m) | Modify, ModifyAll, Rename |
Delete (d) | Delete, DeleteAll |
Calls through the implicit Rec variable inside table objects are included (for example, Rec.Modify() in a table procedure).
Report and query dataitem elements require read (r) permissions for their source table.
XmlPort tableelement nodes require permissions based on the Direction property:
| Direction | Required permissions |
|---|---|
| Import | Insert (i) when AutoSave = true (default), Modify (m) when AutoReplace = true or AutoUpdate = true (defaults) |
| Export | Read (r) |
| Both | All of the above |
Setting AutoSave, AutoReplace, or AutoUpdate to false suppresses the corresponding requirement.
Exceptions
The diagnostic is suppressed when any of the following conditions apply:
- The target table is a system table (ID > 2,000,000,000)
- The codeunit is a test codeunit with
TestPermissions = Disabled - The containing object is a
permissionsetorpermissionsetextension(these declare permissions structurally, not for access control)
The diagnostic also recognizes multiple permission sources. If any source covers the required operation, no diagnostic is reported.
Object-level Permissions property is the primary source:
codeunit 50100 "My Codeunit"
{
Permissions = tabledata Customer = r;
procedure DoSomething()
var
Cust: Record Customer;
begin
Cust.FindFirst(); // No diagnostic
end;
}
Table-level InherentPermissions property grants permissions to all callers:
table 50100 "My Table"
{
InherentPermissions = rimd;
}
Method-level [InherentPermissions] attribute grants permissions for a single procedure:
[InherentPermissions(PermissionObjectType::TableData, Database::Customer, 'r')]
procedure ReadCustomer()
Page SourceTable exemption covers all CRUD on the page’s own source table, including in page extensions. A page that sets SourceTable = Customer does not need to declare permissions for Customer.
Namespace-qualified references (tabledata MyNamespace."My Table" = r) and object ID references (tabledata 50100 = r) are both recognized.
Temporary tables
Temporary tables never touch the database, so they never require permissions. The diagnostic is suppressed for every way a temporary table can be implemented:
- A record variable marked with the
temporarykeyword (var Rec: Record Customer temporary;) - A table object declared with
TableType = Temporary(a plainvar Rec: Record MyTempTable;whereMyTempTableis a temporary table) - A page with
SourceTableTemporary = true(covered by the pageSourceTableexemption) - A report data item or XMLPort table element with
UseTemporary = true
Temporary tables don’t require the user to have permissions on the underlying table. Because temporary table data is held only in memory and never read from or written to the database, the permission system doesn’t apply. […] This behavior applies regardless of how the temporary table is implemented—whether by using the
TableTypeproperty, a temporary record variable, or theSourceTableTemporaryproperty on a page.
— Temporary tables on Microsoft Learn
See also
- Permissions on database objects on Microsoft Learn
- InherentPermissions property on Microsoft Learn
- Indirect permissions on Microsoft Learn