home Home build Tools bug_report Errors menu_book Guides lightbulb Tips extension Extensions folder_open Resources info About
search
error

System.DmlException: Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []

What does this error mean?

This error occurs when Apex code (or an automated process) attempts to create or update a record that references another record the running user does not have read or edit access to. Salesforce enforces record-level security even in system context operations that involve cross-object relationships.

The phrase "cross-reference entity" refers to a lookup or master-detail field pointing to a record in another object. If the running user cannot see that target record, the DML fails with this error.

warning

Important: This error fires based on the running user's access — not the org's OWD or the system admin's access. In triggers, the running user is whoever performed the triggering action. In scheduled jobs or future methods, it is the user who scheduled or invoked the job.

Common Causes

1. Lookup to a Record the User Cannot See

The most common cause. A trigger or automation creates a record with a lookup field pointing to a record (e.g., an Account) that the running user's sharing rules restrict. Even if the running user can create the child record, they cannot link it to a parent they cannot view.

2. OWD Set to Private on the Parent Object

When the Organisation-Wide Default (OWD) for a parent object is set to Private, users only see records they own (or that sharing rules explicitly share with them). A lookup to a privately-owned record owned by another user will fail for users who don't have access.

3. Running in User Mode Without Sufficient Access

Code that runs in User Mode (WITH USER_MODE SOQL clause or the AccessLevel.USER_MODE DML flag) inherits the running user's CRUD and FLS. If that user lacks access to the referenced record, the DML fails.

4. Flow or Process Builder Automation

Record-triggered flows run in system context by default, but flows launched via user interaction (screen flows, quick actions) run as the current user. A cross-object update in a user-context flow can trigger this error for restricted users.

5. Integration User with Restricted Profile

API integrations using a dedicated integration user profile may lack the sharing access required to reference records owned by other users, causing failures when creating related records.

Scenario Root Cause Fix Approach
Trigger creates child record with Account lookup OWD = Private on Account; running user doesn't own it Add sharing rule or use without sharing
Flow updates Opportunity related to restricted Account User-context flow, user lacks Account access Grant sharing or reconfigure flow context
Integration creates Case with Contact lookup Integration user profile doesn't see Contact Adjust integration user sharing settings
Database.update(record, AccessLevel.USER_MODE) Explicit user-mode DML, user lacks access Switch to SYSTEM_MODE or fix user's access

How to Fix It

Solution 1: Use without sharing on the Handler Class

If your Apex logic is intentionally designed to operate with elevated access (e.g., system automation that should bypass record-level security), declare the class without sharing. Use this carefully — it bypasses all sharing rules for that class's execution.

Apex
// Explicitly bypass sharing — use only when appropriate
public without sharing class CaseCreationService {

    public static void createRelatedCases(List<Account> accounts) {
        List<Case> cases = new List<Case>();
        for (Account acc : accounts) {
            cases.add(new Case(
                AccountId = acc.Id,
                Subject = 'Auto-generated: ' + acc.Name,
                Status = 'New'
            ));
        }
        insert cases;
    }
}

Solution 2: Diagnose Errors with Database.insert(allOrNone:false)

Use partial DML with allOrNone = false to isolate which records are failing and log meaningful error information instead of letting the whole transaction roll back.

Apex
List<Database.SaveResult> results =
    Database.insert(recordsToInsert, false);

for (Integer i = 0; i < results.size(); i++) {
    if (!results[i].isSuccess()) {
        for (Database.Error err : results[i].getErrors()) {
            if (err.getStatusCode() ==
                StatusCode.INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY) {
                System.debug('Access error on record: '
                    + recordsToInsert[i].Id
                    + ' — ' + err.getMessage());
            }
        }
    }
}

Solution 3: Add a Sharing Rule for the Referenced Object

If the OWD is Private and you need certain users or groups to see specific records, configure sharing rules in Setup. This is the safest approach — it preserves your security model while granting the required access.

info

Go to Setup → Security → Sharing Settings, find the object with OWD set to Private, and under Sharing Rules click New. Define the criteria (owner or record criteria) and grant Read or Read/Write access to the appropriate user group, role, or territory.

Solution 4: Use System.runAs() in Tests to Reproduce

Always write tests that reproduce the sharing scenario to confirm your fix works correctly under the actual user context.

Apex — Test Class
@isTest
private class CaseCreationServiceTest {

    @isTest
    static void testCreateAsRestrictedUser() {
        // Create a user with a restricted profile
        User restrictedUser = [
            SELECT Id FROM User
            WHERE Profile.Name = 'Standard User'
            LIMIT 1
        ];

        Account acc = new Account(Name = 'Test Corp');
        insert acc;

        // Simulate running as the restricted user
        System.runAs(restrictedUser) {
            Test.startTest();
            CaseCreationService.createRelatedCases(
                new List<Account>{ acc }
            );
            Test.stopTest();
        }

        List<Case> cases = [SELECT Id FROM Case];
        System.assertEquals(1, cases.size(), 'Case should be created');
    }
}
lightbulb

Pro Tip: Use Salesforce Inspector or Setup → Permission Set Assignments to quickly check what record access a specific user has. The User Access Summary in Setup (Lightning) shows exactly which sharing rules apply to a given user for any object.