How to get around table protection in AL

A new “wall” has been erected around specific tables in AL. Making it more challenging to access information that you might need, but there’s a way. Check out the video:

https://youtu.be/Bg7z9FZvX6o

In this video, Erik demonstrates a practical workaround for accessing tables in Business Central that are marked with Access = Internal protection. Using a real-world scenario involving the Shopify integration, he shows how RecordRef can bypass table protection levels when you need to read data from otherwise inaccessible tables.

The Problem: Table Protection in Business Central

Erik starts with a real-world story: while customizing the Shopify integration to Business Central, his team needed to access data that wasn’t moving across properly. They tracked it down to a table called Shopify Data Capture — sounds like a great place to find data, right?

However, when trying to declare a variable of that table type in AL, they ran into a wall:

“Shopify Data Capture is inaccessible due to its protection level.”

Looking at the table definition (using F12 to navigate to it), the culprit becomes clear: the table has its Access property set to Internal. This means the table is only accessible from within the app that defines it — in this case, the Shopify connector app itself. You cannot directly reference it from your own extension.

The Solution: RecordRef

The workaround is straightforward: use a RecordRef instead of a direct table reference. While AL’s compiler prevents you from declaring a record variable of an internal table, RecordRef operates at a lower level using table IDs, effectively bypassing the compile-time protection check.

Here’s the approach Erik demonstrates:

var
    Ref: RecordRef;
    FRef: FieldRef;
    I: Integer;
begin
    Ref.Open(Database::"Shpfy Data Capture");
    Ref.FindFirst();
    FRef := Ref.Field(2); // Field number 2 is "Link to Table"
    I := FRef.Value;
    Message(Format(FRef.Value));
end;

Even though IntelliSense initially shows that the table name is recognized when using Database::"Shpfy Data Capture", the key difference is that RecordRef.Open takes an integer (the table ID) at runtime, so the protection level doesn’t block you.

Working with FieldRef.Value (Joker Types)

Erik takes a brief but important detour to explain how FieldRef.Value works. The value returned by FieldRef.Value is what’s known as a Joker type in AL — a special variant-like type that can hold any value.

Key things to know about Joker types:

  • You cannot declare a variable of Joker type directly — there’s no var x: Joker in AL.
  • You can assign a Joker value to a variable if the underlying type matches. For example, if the field is an Integer, you can assign it to an Integer variable.
  • If you assign it to a mismatched type (e.g., assigning an Integer field value to a Date variable), the code will compile but will fail at runtime.
  • You can pass a Joker value into any function that also accepts a Joker parameter — Message() and Format() both accept Joker parameters, which is why they work seamlessly.

Why Does RecordRef Work?

The reason RecordRef bypasses table protection is fundamental to how Business Central works internally. Many core platform features — configuration packages, data migration tools, and other system functionality — are built on RecordRef. The platform needs to be able to access any table dynamically regardless of its protection level, so RecordRef is not subject to the same compile-time access restrictions as direct record variables.

VS Code Tip: Italic Tabs and Navigation

Erik also shares a VS Code tip he discovered (and invites viewers to share shortcuts he might not know about):

  • When you press F12 (Go to Definition), VS Code opens the file in a preview tab — shown in italic text on the tab header.
  • If you F12 into something else, it replaces the preview tab — your previous file disappears.
  • To pin a preview tab and prevent it from being replaced, simply double-click on the tab. The text will change from italic to regular, and subsequent F12 navigations will open in a new tab instead.

Summary

If you encounter the error “[Table] is inaccessible due to its protection level” in Business Central AL development, all is not lost. Using RecordRef and FieldRef, you can dynamically access the table’s data at runtime, bypassing the Access = Internal restriction. This is particularly useful when third-party apps (like the Shopify connector) mark tables as internal but store data you need for your customizations. It’s worth noting that this is somewhat of a workaround — the table was marked internal for a reason — but when the data isn’t available anywhere else, RecordRef is your friend.