sschmid/Entitas · error · EntityIsNotEnabledException
Cannot destroy !
Error message
Cannot destroy {this}! What it means
Thrown by Entity.Destroy when the entity is already destroyed/disabled. Destroy dispatches OnDestroyEntity; Entitas forbids destroying an entity twice because the destroy process (retainer release, component teardown, pool return) must run exactly once.
Solutions
- Guard with if (entity.isEnabled) entity.Destroy();
- Ensure only one system owns the destroy decision for an entity class
- Unsubscribe listeners in OnDestroyEntity handlers so post-destroy callbacks cannot call Destroy again
- Use context.DestroyAllEntities() only once during teardown
Example fix
// before
foreach (var e in _buffer) e.Destroy(); // may double-destroy
// after
foreach (var e in _buffer) {
if (e.isEnabled) {
e.Destroy();
}
} Defensive patterns
Strategy: validation
Validate before calling
if (entity.isEnabled) entity.Destroy();
Type guard
bool CanDestroy(Entity e) => e.isEnabled;
Try / catch
try { entity.Destroy(); }
catch (EntityIsNotEnabledException) { /* already destroyed */ } Prevention
- Give one system sole responsibility for destroying each entity kind
- Check isEnabled in shared destroy helpers
- Unsubscribe from entity events before/at destroy
- Avoid destroying from multiple reactive systems matching the same entities
When it happens
Trigger: Calling entity.Destroy() on an entity already destroyed; destroying in two systems in the same tick; destroying from a listener that itself was triggered by the destroy process; double cleanup in teardown code.
Common situations: Multiple reactive systems matching the same entity and each destroying it; application shutdown paths that destroy entities unconditionally; listener callbacks not unsubscribed before destroy.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot remove component
- Cannot replace component
- Cannot get component
- EntityIsAlreadyRetainedByOwnerException(_entity, owner)
- EntityIsNotRetainedByOwnerException(_entity, owner)
AI-assisted analysis of sschmid/Entitas@37547d1bd2 (2026-09-14).
Data as JSON: /api/errors/a7daba4332b86c5b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Entitas/Entity/Entity.cs:367
/// Releases the entity. An owner can only release an entity
/// if it retains it.
/// Retain/Release is part of AERC (Automatic Entity Reference Counting)
/// and is used internally to prevent pooling retained entities.
/// If you use retain manually you also have to
/// release it manually at some point.
public void Release(object owner)
{
_aerc.Release(owner);
if (_aerc.RetainCount == 0)
OnEntityReleased?.Invoke(this);
}
// Dispatches OnDestroyEntity which will start the destroy process.
public void Destroy()
{
if (!_isEnabled)
throw new EntityIsNotEnabledException($"Cannot destroy {this}!");
OnDestroyEntity?.Invoke(this);
}
// This method is used internally. Don't call it yourself.
// Use entity.Destroy();
public void InternalDestroy()
{
_isEnabled = false;
RemoveAllComponents();
OnComponentAdded = null;
OnComponentReplaced = null;
OnComponentRemoved = null;
OnDestroyEntity = null;
}
// Do not call this method manually. This method is called by the context.
public void RemoveAllOnEntityReleasedHandlers() => OnEntityReleased = null;View on GitHub (pinned to 37547d1bd2)