BabylonJS/Babylon.js · error

Circular dependency detected!

Error message

Circular dependency detected!

What it means

DependencyGraph.walk performs a topological sort: it repeatedly visits elements whose dependencies have all been satisfied. If elements remain in _list after the traversal completes, some form of cycle (or dependency on a never-added element) prevents ordering, so it logs the remaining set and throws this error.

Source

Thrown at packages/dev/smartFilters/src/optimization/dependencyGraph.ts:93

            const requiredBy = this._requiredBy.get(element);
            if (requiredBy) {
                for (const dependingElement of requiredBy) {
                    const dependencies = this._dependOn.get(dependingElement);

                    if (dependencies) {
                        dependencies.delete(element);

                        if (dependencies.size === 0) {
                            toVisit.push(dependingElement);
                        }
                    }
                }
            }
        }

        if (this._list.size > 0) {
            Logger.Error(JSON.stringify(this._list));
            throw new Error("Circular dependency detected!");
        }
    }
}

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Inspect the JSON logged by Logger.Error right before the throw — it lists the elements stuck in the cycle.
  2. Remove the cyclic connection/dependency between the reported elements.
  3. Ensure every element passed to addDependency was first registered with addElement.
  4. If walk() is called on a shared graph, note it mutates state — build a fresh graph for each walk.

Example fix

// before
graph.addDependency(a, b);
graph.addDependency(b, a); // cycle
// after
graph.addDependency(a, b);
graph.addDependency(b, c); // acyclic chain
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify no element depends on an unregistered element before walking
for (const [el, deps] of dependOnPairs) {
  if (!registered.has(el) || !deps.every(d => registered.has(d))) {
    throw new Error("Dependency on unregistered element");
  }
}

Type guard

null

Try / catch

try {
  graph.walk(processElement);
} catch (e) {
  if (e.message === "Circular dependency detected!") {
    // Logger.Error already dumped the stuck elements; inspect that set to locate the cycle
    console.error("Filter graph contains a feedback loop; check connections between logged blocks");
  } else throw e;
}

Prevention

When it happens

Trigger: Calling walk() on a graph where addDependency created a cycle (A depends on B, B depends on A), or where an element was given a dependency via addDependency but that dependency was never added via addElement, so it can never be satisfied/visited.

Common situations: Optimizer graph construction on a filter whose block connections form a feedback loop; building a custom runtime graph with a dependency on a node that was never registered; a bug in custom block dependency wiring.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/a013b4048a86581e. Report an issue: GitHub.