BabylonJS/Babylon.js · error · Error
Service '${service.friendlyName}' has dependents: ${Array.fr
Error message
Service '${service.friendlyName}' has dependents: ${Array.from(serviceDependents)
.map((dependent) => dependent.friendlyName)
.join(", ")} What it means
_removeService refuses to remove a service while other services still depend on it: _serviceDependents.get(service) is non-empty. dispose() removes instances in reverse instantiation order, so this error indicates dependency bookkeeping is out of order or a dependent was never released.
Source
Thrown at packages/dev/sharedUiComponents/src/modularTool/modularity/serviceContainer.ts:179
dependentDefinitions.delete(consumer);
if (dependentDefinitions.size === 0) {
this._serviceDependents.delete(definition);
}
}
return;
}
this._parent?._removeDependentFromChain(contract, consumer);
}
private _removeService(service: WeaklyTypedServiceDefinition) {
if (this._isDisposed) {
throw new Error(`'${this._friendlyName}' container is disposed.`);
}
const serviceDependents = this._serviceDependents.get(service);
if (serviceDependents && serviceDependents.size > 0) {
throw new Error(
`Service '${service.friendlyName}' has dependents: ${Array.from(serviceDependents)
.map((dependent) => dependent.friendlyName)
.join(", ")}`
);
}
// NOTE: The service instance could be undefined, as the service factory for a service that does not produce any contracts is not required to return an actual service instance.
const serviceInstance = this._serviceInstances.get(service);
this._serviceInstances.delete(service);
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);
View on GitHub (pinned to 0592b347b8)
Solutions
- Release dependents first (let their cleanup run) before removing/disposing the producer.
- Ensure all consumers call the container's dependent-removal API in their dispose.
- Await all async module startup/teardown before disposing the container.
- Inspect the error's dependent list to find which consumers still hold references.
Example fix
// before consumer.dispose(); // never unregisters as dependent container.dispose(); // throws: producer has dependents // after consumer.dispose(); // internally calls container.removeDependent(producerContract, consumerDef) container.dispose();
Defensive patterns
Strategy: validation
Validate before calling
// Release dependents before removing a producer
function safeRemoveProducer(container, producerContract, consumerDef) {
// consumer must have unregistered itself first
consumerDef.dispose?.(); // triggers removeDependent internally
// then removal/dispose of the producer is safe
} Try / catch
// try {
// container.dispose();
// } catch (e) {
// if (String(e.message).startsWith("Service '") && e.message.includes("has dependents:")) {
// console.error("Release these consumers first:", e.message);
// }
// throw e;
// } Prevention
- Consumers must call removeDependent (or equivalent) in their own dispose.
- Await all async startup/teardown before disposing the container.
- Remove services in reverse dependency order; prefer container.dispose() over manual removal.
When it happens
Trigger: Disposing the container while a dependent service was registered via dependencies() but not unregistered; manually removing a producer service that still has dependents; dependents added after the reverse-order teardown snapshot was taken.
Common situations: Custom removal of a shared/logger-like service consumed by many modules; dispose racing with a module still resolving dependencies (async startup not awaited); leaking dependent registrations because removeDependent was never called on consumer teardown.
Related errors
- Service '${contract.toString()}' has not been instantiated i
- Function not injected yet. Use the factory to create the plu
- There is no NavMesh generated.
- There is no TileCache generated.
- No volume subnode
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/7214dad69fb63cf4.
Report an issue: GitHub.