sschmid/Entitas · error · EntityIsNotEnabledException

Cannot remove component

Error message

Cannot remove component '{_contextInfo.ComponentNames[index]}' from {this}!

What it means

Thrown by Entity.RemoveComponent when the entity has been destroyed (_isEnabled == false). Even before checking whether the component exists, Entitas rejects any component operation on a disabled (destroyed) entity, because its component table is no longer meaningful.

Solutions

  1. Guard with if (entity.isEnabled) before removing components
  2. Unsubscribe from OnComponentRemoved/OnDestroyEntity when the entity is destroyed so stale callbacks never run
  3. Retain the entity (SafeAERC) if it must outlive its context lifetime legitimately
  4. Re-fetch entities from the context each update rather than holding destroyed references

Example fix

// before
entity.RemoveHealth(); // throws if entity was destroyed
// after
if (entity.isEnabled && entity.hasHealth) {
    entity.RemoveHealth();
}
Defensive patterns

Strategy: validation

Validate before calling

if (entity.isEnabled && entity.HasComponent(index)) entity.RemoveComponent(index);

Type guard

bool CanRemove(Entity e, int index) => e.isEnabled && e.HasComponent(index);

Try / catch

try { entity.RemoveComponent(index); }
catch (EntityIsNotEnabledException) { /* entity already destroyed; nothing to do */ }

Prevention

When it happens

Trigger: Calling entity.RemoveComponent(index) or a generated e.RemovePosition() on an entity that was already destroyed via Destroy() or reclaimed by the context.

Common situations: Cleanup systems running after teardown; listeners firing after entity destruction; a destroyed entity kept in a group snapshot and then mutated in a later frame.

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


AI-assisted analysis of sschmid/Entitas@37547d1bd2 (2026-09-14). Data as JSON: /api/errors/77280047d0a106f1. Report an issue: GitHub.

Appendix: source

Thrown at src/Entitas/Entity/Entity.cs:157

                    $"Cannot add component '{_contextInfo.ComponentNames[index]}' to {this}!",
                    "You should check if an entity already has the component before adding it or use entity.ReplaceComponent()."
                );

            _components[index] = component;
            _componentsCache = null;
            _componentIndexesCache = null;
            _toStringCache = null;
            OnComponentAdded?.Invoke(this, index, component);
        }

        /// Removes a component at the specified index.
        /// You can only remove a component at an index if it exists.
        /// The preferred way is to use the
        /// generated methods from the code generator.
        public void RemoveComponent(int index)
        {
            if (!_isEnabled)
                throw new EntityIsNotEnabledException($"Cannot remove component '{_contextInfo.ComponentNames[index]}' from {this}!");

            if (!HasComponent(index))
                throw new EntityDoesNotHaveComponentException(index,
                    $"Cannot remove component '{_contextInfo.ComponentNames[index]}' from {this}!",
                    "You should check if an entity has the component before removing it.");

            HandleComponent(index, null);
        }

        /// Replaces an existing component at the specified index
        /// or adds it if it doesn't exist yet.
        /// The preferred way is to use the
        /// generated methods from the code generator.
        public void ReplaceComponent(int index, IComponent component)
        {
            if (!_isEnabled)
                throw new EntityIsNotEnabledException($"Cannot replace component '{_contextInfo.ComponentNames[index]}' on {this}!");

View on GitHub (pinned to 37547d1bd2)