BabylonJS/Babylon.js · error · Error
'${this._friendlyName}' container cannot be disposed because
Error message
'${this._friendlyName}' container cannot be disposed because it has ${this._children.size} active child container(s). What it means
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.
Source
Thrown at packages/dev/sharedUiComponents/src/modularTool/modularity/serviceContainer.ts:207
serviceInstance?.dispose?.();
service.produces?.forEach((contract) => {
this._serviceDefinitions.delete(contract);
});
// Remove this service as a dependent from each of its consumed dependencies (local or in parent chain).
service.consumes?.forEach((contract) => {
this._removeDependentFromChain(contract, service);
});
}
/**
* Disposes the service container and all contained services.
* Throws if this container is still a parent of any live child containers.
*/
public dispose() {
if (this._children.size > 0) {
throw new Error(`'${this._friendlyName}' container cannot be disposed because it has ${this._children.size} active child container(s).`);
}
Array.from(this._serviceInstances.keys()).reverse().forEach(this._removeService.bind(this));
this._serviceInstances.clear();
this._serviceDependents.clear();
this._serviceDefinitions.clear();
this._parent?._children.delete(this);
this._isDisposed = true;
}
}
View on GitHub (pinned to 0592b347b8)
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.
Example fix
// before parent.dispose(); // throws: has 2 active child containers // after children.forEach((c) => c.dispose()); parent.dispose();
Defensive patterns
Strategy: validation
Validate before calling
// const children = getActiveChildren(parent); // your own registry // if (children.length) children.forEach((c) => c.dispose()); // parent.dispose();
Try / catch
// try {
// parent.dispose();
// } catch (e) {
// if (e.message.includes("active child container")) {
// throw new Error("Dispose child containers before the parent", { cause: e });
// }
// throw e;
// } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- There is no NavMesh generated.
- There is no TileCache generated.
- No volume subnode
- Disconnect failed
- Engine does not have gl rendering context.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/fc52c790efd5026b.
Report an issue: GitHub.