Salesforce record id written as a literal

ID

apex.correctness.hardcoding_id

Severity

high

Remediation Complexity

medium

Remediation Risk

medium

Remediation Effort

medium

Resource

Api Usage

Language

Apex

Description

Reports a string literal shaped like a 15- or 18-character Salesforce id (a 0 or a key prefix, mixed case and digits).

Rationale

Record ids are assigned per org. The id of a profile, a record type, a queue or a custom setting in production is a different id in every sandbox, in every scratch org and in every subscriber org that installs the package. Code holding one compiles everywhere and is wrong everywhere else: the query returns nothing, the assignment points at a record that does not exist, and the failure is an empty result or a null dereference rather than anything that names the id. Sandbox refreshes re-issue ids too, so the same code can start failing in a sandbox that used to work.

The following code illustrates the pattern detected by this rule:

public class ProfileLookup {

    // FLAGGED: Salesforce record id written as a literal
    private static final Id SYSTEM_ADMIN = '00e5g000001ABCDAA4';

    public List<User> admins() {
        // FLAGGED: Salesforce record id written as a literal
        return [SELECT Id FROM User WHERE ProfileId = '00e5g000001ABCD'];
    }

    public List<User> adminsByName() {
        Profile p = [SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1];
        return [SELECT Id FROM User WHERE ProfileId = :p.Id];
    }

    public String label() {
        return 'System Administrator';
    }

    public String developerName() {
        return 'business_account_type';
    }
}

Remediation

Resolve the record by a stable name at runtime - query the profile by Name, the record type by developer name, the queue by DeveloperName - and cache the id in a static for the length of the transaction. Where an id genuinely has to be configured per org, put it in Custom Metadata or a Custom Setting so it can be set per environment without a deployment.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved