{"record":{"id":"fc52c790efd5026b","repo":"BabylonJS/Babylon.js","slug":"this-friendlyname-container-cannot-be-dispos","errorCode":null,"errorMessage":"'${this._friendlyName}' container cannot be disposed because it has ${this._children.size} active child container(s).","messagePattern":"'(.+?)' container cannot be disposed because it has (.+?) active child container\\(s\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/sharedUiComponents/src/modularTool/modularity/serviceContainer.ts","lineNumber":207,"sourceCode":"        serviceInstance?.dispose?.();\r\n\r\n        service.produces?.forEach((contract) => {\r\n            this._serviceDefinitions.delete(contract);\r\n        });\r\n\r\n        // Remove this service as a dependent from each of its consumed dependencies (local or in parent chain).\r\n        service.consumes?.forEach((contract) => {\r\n            this._removeDependentFromChain(contract, service);\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Disposes the service container and all contained services.\r\n     * Throws if this container is still a parent of any live child containers.\r\n     */\r\n    public dispose() {\r\n        if (this._children.size > 0) {\r\n            throw new Error(`'${this._friendlyName}' container cannot be disposed because it has ${this._children.size} active child container(s).`);\r\n        }\r\n\r\n        Array.from(this._serviceInstances.keys()).reverse().forEach(this._removeService.bind(this));\r\n        this._serviceInstances.clear();\r\n        this._serviceDependents.clear();\r\n        this._serviceDefinitions.clear();\r\n        this._parent?._children.delete(this);\r\n        this._isDisposed = true;\r\n    }\r\n}\r\n","sourceCodeStart":189,"sourceCodeEnd":218,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/sharedUiComponents/src/modularTool/modularity/serviceContainer.ts#L189-L218","documentation":"dispose() refuses to dispose a container that still has live child containers in _children. Child containers may resolve services through this parent, so disposing the parent first would orphan them; children must be disposed before their parent.","triggerScenarios":"Calling parentContainer.dispose() while createChild/derived child containers are still alive; a child created but its dispose never called in cleanup; children tracked outside the container so teardown order is wrong.","commonSituations":"Tool shutdown disposing the root container while plugin scopes (children) remain open; leaked child containers from aborted initialization; tests forgetting per-test child container cleanup.","solutions":["Dispose all child containers first, then the parent (depth-first teardown).","Keep a registry of created children in the owner and dispose them in cleanup.","Make parent disposal automatically dispose children only if the library API permits; otherwise fix ordering at call sites.","In tests, use afterEach to dispose any containers created during the test."],"exampleFix":"// before\nparent.dispose(); // throws: has 2 active child containers\n// after\nchildren.forEach((c) => c.dispose());\nparent.dispose();","handlingStrategy":"validation","validationCode":"// const children = getActiveChildren(parent); // your own registry\n// if (children.length) children.forEach((c) => c.dispose());\n// parent.dispose();","typeGuard":null,"tryCatchPattern":"// try {\n//   parent.dispose();\n// } catch (e) {\n//   if (e.message.includes(\"active child container\")) {\n//     throw new Error(\"Dispose child containers before the parent\", { cause: e });\n//   }\n//   throw e;\n// }","preventionTips":["Track every created child container and dispose depth-first on teardown.","Fix child leaks: abort paths must dispose already-created children.","In tests, dispose containers in afterEach."],"tags":["lifecycle","disposal","container-hierarchy"],"backgroundTag":"container-has-active-children","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}