{"record":{"id":"a013b4048a86581e","repo":"BabylonJS/Babylon.js","slug":"circular-dependency-detected","errorCode":null,"errorMessage":"Circular dependency detected!","messagePattern":"Circular dependency detected!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/smartFilters/src/optimization/dependencyGraph.ts","lineNumber":93,"sourceCode":"            const requiredBy = this._requiredBy.get(element);\r\n            if (requiredBy) {\r\n                for (const dependingElement of requiredBy) {\r\n                    const dependencies = this._dependOn.get(dependingElement);\r\n\r\n                    if (dependencies) {\r\n                        dependencies.delete(element);\r\n\r\n                        if (dependencies.size === 0) {\r\n                            toVisit.push(dependingElement);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        if (this._list.size > 0) {\r\n            Logger.Error(JSON.stringify(this._list));\r\n            throw new Error(\"Circular dependency detected!\");\r\n        }\r\n    }\r\n}\r\n","sourceCodeStart":75,"sourceCodeEnd":97,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/smartFilters/src/optimization/dependencyGraph.ts#L75-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the JSON logged by Logger.Error right before the throw — it lists the elements stuck in the cycle.","Remove the cyclic connection/dependency between the reported elements.","Ensure every element passed to addDependency was first registered with addElement.","If walk() is called on a shared graph, note it mutates state — build a fresh graph for each walk."],"exampleFix":"// before\ngraph.addDependency(a, b);\ngraph.addDependency(b, a); // cycle\n// after\ngraph.addDependency(a, b);\ngraph.addDependency(b, c); // acyclic chain","handlingStrategy":"try-catch","validationCode":"// Verify no element depends on an unregistered element before walking\nfor (const [el, deps] of dependOnPairs) {\n  if (!registered.has(el) || !deps.every(d => registered.has(d))) {\n    throw new Error(\"Dependency on unregistered element\");\n  }\n}","typeGuard":"null","tryCatchPattern":"try {\n  graph.walk(processElement);\n} catch (e) {\n  if (e.message === \"Circular dependency detected!\") {\n    // Logger.Error already dumped the stuck elements; inspect that set to locate the cycle\n    console.error(\"Filter graph contains a feedback loop; check connections between logged blocks\");\n  } else throw e;\n}","preventionTips":["Design filter graphs without feedback loops (no connection path from a block back into itself).","Register every element with addElement before calling addDependency.","Build a fresh DependencyGraph for each walk — walk mutates the graph.","Check the Logger.Error JSON output to identify the exact cyclic blocks."],"tags":["dependency-graph","circular-dependency","topological-sort"],"backgroundTag":"circular-dependency-detected","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}