sschmid/Entitas · error · EntityIsNotEnabledException

Cannot replace component

Error message

Cannot replace component '{_contextInfo.ComponentNames[index]}' on {this}!

What it means

Thrown by Entity.ReplaceComponent when the entity has been destroyed (not enabled). ReplaceComponent would otherwise add-or-replace, but on a disabled entity any mutation is rejected with EntityIsNotEnabledException.

Solutions

  1. Check entity.isEnabled before Replace; skip or re-create the entity
  2. Subscribe to OnDestroyEntity to purge entities from your update lists
  3. Re-acquire the entity from context.GetGroups()/GetEntities() instead of caching
  4. Retain the entity if it must survive destroy while you finish writing to it

Example fix

// before
_entity.ReplaceVelocity(x, y); // throws after destroy
// after
if (!_entity.isEnabled) {
    _entity = _context.CreateEntity();
}
_entity.ReplaceVelocity(x, y);
Defensive patterns

Strategy: validation

Validate before calling

if (!entity.isEnabled) return; // or re-create
entity.ReplaceComponent(index, component);

Type guard

bool CanReplace(Entity e, int index) => e.isEnabled;

Try / catch

try { entity.ReplaceComponent(index, component); }
catch (EntityIsNotEnabledException) { /* skip update for destroyed entity */ }

Prevention

When it happens

Trigger: Calling entity.ReplaceComponent(index, component) or a generated e.ReplacePosition(...) on an entity destroyed earlier (via Destroy() or context destruction).

Common situations: Update loops that cache entities and keep calling Replace on them after they were destroyed by another system; reactive systems processing an event for an entity destroyed mid-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/30c474f53f71b64d. Report an issue: GitHub.

Appendix: source

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

            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}!");

            if (HasComponent(index))
                HandleComponent(index, component);
            else if (component != null)
                AddComponent(index, component);
        }

        void HandleComponent(int index, IComponent newComponent)
        {
            var previousComponent = _components[index];
            if (newComponent != previousComponent)
            {
                _components[index] = newComponent;
                _componentsCache = null;
                _toStringCache = null;
                if (newComponent != null)
                {
                    OnComponentReplaced?.Invoke(this, index, previousComponent, newComponent);

View on GitHub (pinned to 37547d1bd2)