Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Platform

This page can't be displayed. Try reloading the page, or contact your administrator.

Generic Lightning page failure. The actual cause is in the browser console. Common culprits: an LWC threw a runtime error, a permissions check failed for one component, or the page exceeds component-count limits. Reload won't fix anything; you have to look at DevTools.

Also seen asThis page can't be displayed·Try reloading the page·page can't be displayed lightning·Lightning page error contact administrator

A sales operations team rolls out a redesigned Opportunity record page. The page combines the standard layout with eleven custom Lightning Web Components covering pipeline health, related contacts, recent emails, a deal score, document signatures, and several quote-related widgets. Users see the page for two days. On Thursday morning, half the team reports the same blocking message: "This page can't be displayed. Try reloading the page, or contact your administrator." The other half see a partial page with missing tabs. Productivity grinds to a halt.

What the platform is checking

Lightning record pages have soft and hard limits on how many components a page can hold and on how much work those components can do during initialization. The Lightning App Builder reports certain limits at design time (such as the maximum number of components per region). Other limits apply at runtime, including the cumulative load time, the cumulative Apex CPU consumption, and the response size of the controllers backing the components.

The generic "This page can't be displayed" message is what Salesforce shows when the page experience fails to render within an acceptable time or when one or more components hit a load-time limit. The platform does not surface the underlying cause to the end user because exposing the specifics would leak implementation details and would not help the non-admin viewer.

The cause sits in one of several categories. The page has more components in a single region than the platform supports. A component takes too long to load and stalls page rendering. A controller called from a component throws an unexpected exception that bubbles up through the framework. A component depends on a feature that the current user's permission set does not allow. The Lightning Performance Inspector or the browser developer console usually reveals which component is responsible.

The platform's reasoning is user safety. A record page that takes 30 seconds to render is worse than no page at all because users walk away thinking the system is broken. The render-or-fail policy ensures pages either work quickly or visibly fail so an admin can fix the design.

The broken example

A custom component on the Opportunity record page that loads twelve related records in parallel:

// dealScoreCard.js
import { LightningElement, api, wire } from 'lwc';
import getOpportunityDetails from '@salesforce/apex/OpportunityScoreController.getOpportunityDetails';

export default class DealScoreCard extends LightningElement {
    @api recordId;
    deal;
    error;

    @wire(getOpportunityDetails, { opportunityId: '$recordId' })
    wiredDeal({ data, error }) {
        if (data) this.deal = data;
        if (error) this.error = error;
    }
}

The controller:

public class OpportunityScoreController {
    @AuraEnabled(cacheable=true)
    public static OpportunityWrapper getOpportunityDetails(Id opportunityId) {
        OpportunityWrapper w = new OpportunityWrapper();
        w.opp = [SELECT Id, Name, Amount, StageName FROM Opportunity WHERE Id = :opportunityId];
        w.contacts = [SELECT Contact.Name FROM OpportunityContactRole WHERE OpportunityId = :opportunityId];
        w.activities = [SELECT Id, Subject FROM Task WHERE WhatId = :opportunityId ORDER BY CreatedDate DESC LIMIT 50];
        w.emails = [SELECT Id, Subject, FromAddress FROM EmailMessage WHERE RelatedToId = :opportunityId ORDER BY MessageDate DESC LIMIT 50];
        w.events = [SELECT Id, Subject FROM Event WHERE WhatId = :opportunityId];
        w.notes = [SELECT Id, Title FROM ContentDocumentLink WHERE LinkedEntityId = :opportunityId];
        return w;
    }
    public class OpportunityWrapper {
        @AuraEnabled public Opportunity opp;
        @AuraEnabled public List<OpportunityContactRole> contacts;
        @AuraEnabled public List<Task> activities;
        @AuraEnabled public List<EmailMessage> emails;
        @AuraEnabled public List<Event> events;
        @AuraEnabled public List<ContentDocumentLink> notes;
    }
}

The component itself looks innocent. The controller runs six queries to populate the wrapper. With eleven custom components on the page each running similar controllers, the page issues sixty SOQL queries during initial load. Some queries return large result sets. The cumulative load time pushes past the page's threshold. The framework gives up and shows the blocking message.

A second shape: a component that depends on a custom permission. Users without the permission see the page fail to render rather than seeing the component politely hidden.

A third shape: a component that requires a custom setting that was not deployed to production. The component fails at load time with a clean exception, but the page does not isolate the failure and the whole page errors out.

The fix, three paths

Reduce the number of components per page region. The simplest fix is to consolidate. Two related widgets that show pipeline health and deal score can become one component with a tabbed interface. Three widgets that show related contacts, related cases, and related quotes can become one tabbed component using the standard lightning-tabset. Fewer top-level components means fewer parallel controller calls during initialization.

Lazy-load expensive components. A component that does not need to be visible above the fold can defer its work until the user expands or scrolls to it. The IsVisible flag on a Lightning App Builder region or the lwc:if directive inside a component skips the expensive work until the user interacts:

// dealScoreCard.js
import { LightningElement, api } from 'lwc';

export default class DealScoreCard extends LightningElement {
    @api recordId;
    expanded = false;
    handleExpand() {
        this.expanded = true;
    }
}
<template>
    <lightning-button label="Show deal score" onclick={handleExpand}></lightning-button>
    <template lwc:if={expanded}>
        <c-deal-score-loader record-id={recordId}></c-deal-score-loader>
    </template>
</template>

The expensive loader only mounts when the user requests it. The page renders quickly with a button, and the user opts in to the heavier component.

Trim the controller to return only what the component needs. A controller that returns six lists when the component renders only one is doing five queries' worth of waste. Split the controller into focused methods and let each component call exactly what it needs:

public class OpportunityScoreController {
    @AuraEnabled(cacheable=true)
    public static Opportunity getOpportunity(Id opportunityId) {
        return [SELECT Id, Name, Amount, StageName FROM Opportunity WHERE Id = :opportunityId LIMIT 1];
    }

    @AuraEnabled(cacheable=true)
    public static List<Task> getRecentActivities(Id opportunityId) {
        return [SELECT Id, Subject FROM Task WHERE WhatId = :opportunityId
                ORDER BY CreatedDate DESC LIMIT 10];
    }
}

The deal score component calls getOpportunity. The activity feed component calls getRecentActivities. Each component sees only what it needs and parallel calls do not pile up redundant SOQL.

The fixed example

A consolidated deal-summary component that loads only the headline data:

// dealSummary.js
import { LightningElement, api, wire } from 'lwc';
import getOpportunity from '@salesforce/apex/OpportunityScoreController.getOpportunity';

export default class DealSummary extends LightningElement {
    @api recordId;
    opp;
    error;

    @wire(getOpportunity, { opportunityId: '$recordId' })
    wiredOpp({ data, error }) {
        if (data) this.opp = data;
        if (error) this.error = error;
    }

    get amountDisplay() {
        return this.opp && this.opp.Amount ? '$' + this.opp.Amount.toLocaleString() : '--';
    }
}

The component loads one Opportunity record with four fields. The supporting widgets (activities, emails, contacts) move into a tabbed component that loads each tab's data only when the user clicks the tab. The page now renders in well under a second on initial load.

Edge case: third-party managed package components

Some pages combine first-party components with components from managed packages. A managed-package component that takes 5 seconds to load can drag the entire page past the threshold even when your own components are fast. The fix is to move the slow managed-package component into a less-frequently-viewed tab, into a related list, or onto a different page altogether.

Edge case: dynamic forms and field-level security

Dynamic Forms places individual fields rather than full page sections on a Lightning record page. Each field is a small component with its own metadata. Pages with hundreds of dynamic-form fields can exceed component-count limits. Combining fields into sections and using accordion-style containers keeps the count manageable.

A user without read access to a field still has the field rendered as a component until the framework checks permissions. The permission check itself counts toward initialization work. For pages used by many permission profiles, defining separate page assignments for each profile keeps each rendering simpler.

Edge case: component types versus instances

The Lightning App Builder shows a count of components on the page. The number reflects instances, not types. A page with five different c-deal-summary instances counts as five components even though the type is reused. The architectural fix is to consolidate the data and present multiple aspects from a single instance rather than instancing the same component repeatedly.

Edge case: long-running Apex controllers behind cached wires

A @wire with a controller marked cacheable=true returns from Salesforce's cache layer on subsequent calls. The first call still pays the full latency. A page that has eight cached wires hits the server eight times on first load. Each call has its own latency, and the cumulative load time stacks up even though individual wires are fast.

Bundling related data into a single controller that returns a wrapper object reduces the number of round trips. A wire that returns 60 KB of useful data in one call is faster than six wires that return 10 KB each because the platform amortizes the request overhead.

For controllers that do not need caching (because the underlying data changes frequently), the cacheable=true decoration is a small mistake that causes stale reads. Use cacheable only when the data is genuinely cacheable for the session.

Edge case: component initialization order

Lightning components mount in roughly parallel order on the page. A component that requires data from another component (a child reading a parent's selection, for example) needs explicit coordination. Without it, the dependent component initializes before the data it needs is available, falls back to an empty state, and then re-renders when the data arrives. The re-render counts toward initialization work.

Using lightning-message-channel for cross-component coordination keeps the wiring explicit. Components publish events when their data is ready; subscribers wait for the event before doing their own data fetch.

Defensive habits

Audit record pages periodically. The Lightning App Builder shows component counts and Salesforce Help documents the current thresholds. A page that approaches the threshold today will exceed it after the next feature release.

Use the Lightning Performance Inspector. Chrome DevTools with the Lightning extension exposes load times per component and identifies the slowest controllers. The data tells you which component to optimize first.

Set a component-count budget per record page. A budget of 10 components per page forces consolidation decisions early and keeps pages responsive.

Test pages with realistic user profiles. The admin who builds the page often has full read access to every field and every related list. A sales rep with a narrower profile may see different rendering paths and different errors. Page testing under multiple profiles catches profile-specific failures before production.

Test patterns

Page rendering is not directly testable in Apex; it is tested at the user-experience level. The closest Apex tests are the controller-level tests, which verify that controllers return quickly with reasonable scope:

@IsTest
static void getOpportunityReturnsSingleRecord() {
    Account a = new Account(Name='Test');
    insert a;
    Opportunity o = new Opportunity(
        Name='Test', AccountId=a.Id, StageName='Prospecting',
        CloseDate=Date.today().addDays(30), Amount=1000
    );
    insert o;

    Test.startTest();
    Opportunity result = OpportunityScoreController.getOpportunity(o.Id);
    Test.stopTest();

    System.assertEquals(o.Id, result.Id);
}

At the page level, manual testing with the browser developer tools and the Lightning Performance Inspector catches cases the unit tests cannot.

Diagnosing in production

When users report the blocking message:

  1. Reproduce the page load in your own browser with the user's profile.
  2. Open the browser developer console and look for component errors.
  3. Open the Lightning Performance Inspector and find the slowest controller.
  4. Check the Setup Audit Trail for recent page or component changes.
  5. Temporarily remove the suspected component from the page in the App Builder.
  6. Confirm the page renders cleanly without the component.
  7. Optimize or replace the offending component, then re-add it.

The fix is usually a single component. Once identified, the optimization (lazy load, reduce queries, split into smaller components) is targeted and quick.

Anti-pattern: ignoring the warning state

The Lightning App Builder shows yellow warning indicators when a page approaches limits. Teams that ignore the warnings ship the page, see it work for a few weeks while data volumes are small, and then hit the failure threshold once production data fills out. The warnings are advisory but the design rule is firm: a page in the yellow band today is a failure tomorrow.

Quick recovery checklist

  1. Reproduce the failure.
  2. Use the Performance Inspector to find the slow component.
  3. Remove or lazy-load the component.
  4. Verify the page renders.
  5. Plan a proper redesign if the page consistently approaches limits.

The blocking message resolves once the offending component is fixed. The longer-term work is governance around page design to keep new pages from crossing the same lines.

Further reading from Salesforce

Related dictionary terms

Share this fix

Share on LinkedInShare on X

Related Salesforce errors