Skip to main content
SFDC Developers
Admin

Salesforce Account Parent-Child Circular Relationship: What Happens When You Create a Circular Parent?

Vinay Vernekar · · 3 min read

Context

You create two Account records in Salesforce: a1 and a2. You set a2 as the parent of a1 (i.e., a1.ParentId = a2.Id). Then you try to make a1 the parent of a2 (i.e., set a2.ParentId = a1.Id). What happens?

Short Answer

Salesforce prevents circular parent-child relationships. If you attempt to make a1 the parent of a2 after a2 is already the parent of a1, the platform will block the change and return a validation/API error. Salesforce enforces the Account hierarchy as a directed acyclic graph (a tree), so cycles are not allowed.

Why Salesforce blocks this

Allowing a parent-child cycle would create an infinite loop in hierarchy traversals (ancestors/descendants) and break assumptions used by UI features (Parent Account, Account Hierarchy), sharing calculations, rollups, and many system operations. To keep data integrity and ensure predictable behavior, Salesforce enforces a strict non-recursive parent chain.

How the error appears

- In the Salesforce UI: You will typically see an error message when saving the Account record that indicates a recursive/circular relationship is not allowed.
- Via API (SOAP/REST) or Apex: The save/update will fail with an error indicating a recursive relationship or invalid ParentId update. The exact wording can vary across releases and APIs, but the effect is the same — the transaction is rejected.

How to detect and prevent circular references programmatically

If you need to enforce or proactively detect potential cycles (for bulk updates, integrations, or user-friendly messages), add a server-side check (Apex trigger or before-save flow) that walks the parent chain and ensures the new parent is not a descendant of the current record.

Example: simple Apex pre-check (conceptual)

// Pseudocode - do NOT paste to production without testing
for (Account a : Trigger.new) {
    Id newParentId = a.ParentId;
    if (newParentId == null) continue;

    // Walk up the parent chain from newParentId and look for the current account Id
    Id cursor = newParentId;
    while (cursor != null) {
        if (cursor == a.Id) {
            a.addError('Cannot set parent: this would create a circular account hierarchy.');
            break;
        }
        // Query parent of cursor
        Account p = [SELECT ParentId FROM Account WHERE Id = :cursor LIMIT 1];
        cursor = p.ParentId;
        // Optional: add safety counter to avoid infinite loops
    }
}

Notes: - Use bulk-safe patterns: avoid one SOQL per loop. Instead, collect parent Ids and fetch multiple accounts in batches, then iterate in memory. - For very deep hierarchies or large data volumes, implement an iterative algorithm that loads parent levels in chunks to stay within governor limits.

Best practices

  • Enforce checks in a before-insert / before-update Apex trigger or a server-side Flow to block cycles.
  • Provide clear UI validation messages so users understand why the save failed.
  • When doing data loads, validate parent chains in your ETL/pre-processing step to catch cycles before sending to Salesforce.
  • Consider storing computed hierarchy metadata (e.g., depth, ancestor list) if you need fast ancestor/descendant queries — but ensure the metadata update logic prevents cycles.

Keywords

Salesforce account hierarchy, circular parent relationship, ParentId, recursive relationship, Apex trigger, account parent-child, data integrity

Share this article

Vinay Vernekar

Vinay Vernekar

Salesforce Developer & Founder

Vinay is a seasoned Salesforce developer with over a decade of experience building enterprise solutions on the Salesforce platform. He founded SFDCDevelopers.com to share practical tutorials, best practices, and career guidance with the global Salesforce community.

Comments

Loading comments...

Leave a Comment

Trending Now