EllanJiang/GameFramework · error · GameFrameworkException

Entity group is invalid.

Error message

Entity group is invalid.

What it means

GameFramework throws this when recycling a queued entity whose owning entity group cannot be resolved. During Update, the EntityManager dequeues an entity from m_RecycleQueue, casts entity.EntityGroup to a concrete EntityGroup, and if the reference is null the entity cannot be unspawned back into any group, so the manager aborts with this GameFrameworkException. It indicates an internal invariant violation: an entity entered the recycle queue without a valid, registered group.

Solutions

  1. Ensure entities are only created via EntityGroup.SpawnEntity and only recycled while their group still exists in the EntityManager.
  2. Do not destroy or remove entity groups while entities from that group are still in the recycle queue; call RecycleEntity before group removal.
  3. Verify custom IEntity implementations correctly set EntityGroup and return the concrete GameFramework EntityGroup instance from the EntityGroup property.
  4. Check game shutdown order so the Entity component is not cleared before pending recycles are processed.

Example fix

// before
gameFrameworkEntityGroup.Destroy();
entity.Recycle(); // group already destroyed -> EntityGroup null

// after
if (entityGroup.HasEntity(entity))
{
    entity.Recycle(); // recycle while group still valid
}
gameFrameworkEntityGroup.Destroy();
Defensive patterns

Strategy: validation

Validate before calling

if (entity == null || entity.EntityGroup == null)
{
    // skip recycle or log instead of calling RecycleEntity
    return;
}

Type guard

bool CanRecycle(IEntity entity) => entity?.EntityGroup != null;

Try / catch

try
{
    entityManager.RecycleEntity(entity);
}
catch (GameFrameworkException ex)
{
    Debug.LogWarning($"Recycle failed: {ex.Message}; destroying entity instead");
}

Prevention

When it happens

Trigger: Calling EntityManager.RecycleEntity (directly or via Entity.Recycle) for an entity whose EntityGroup reference is null, or whose group was set to a type that is not the concrete EntityGroup class (failed cast). Also occurs if the entity was obtained outside a registered group or the group was somehow cleared before the deferred recycle processed in Update.

Common situations: Manual entity lifecycle manipulation (spawning/recycling entities bypassing the group API), destroying or clearing an entity group while entities from it are still pending recycle in the queue, custom IEntity implementations that never set EntityGroup, and calling RecycleEntity after shutdown/clear of the entity component.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15). Data as JSON: /api/errors/b379b7b5b0b7620e. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/Entity/EntityManager.cs:171

                m_HideEntityCompleteEventHandler -= value;
            }
        }

        /// <summary>
        /// 实体管理器轮询。
        /// </summary>
        /// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
        /// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
        internal override void Update(float elapseSeconds, float realElapseSeconds)
        {
            while (m_RecycleQueue.Count > 0)
            {
                EntityInfo entityInfo = m_RecycleQueue.Dequeue();
                IEntity entity = entityInfo.Entity;
                EntityGroup entityGroup = (EntityGroup)entity.EntityGroup;
                if (entityGroup == null)
                {
                    throw new GameFrameworkException("Entity group is invalid.");
                }

                entityInfo.Status = EntityStatus.WillRecycle;
                entity.OnRecycle();
                entityInfo.Status = EntityStatus.Recycled;
                entityGroup.UnspawnEntity(entity);
                ReferencePool.Release(entityInfo);
            }

            foreach (KeyValuePair<string, EntityGroup> entityGroup in m_EntityGroups)
            {
                entityGroup.Value.Update(elapseSeconds, realElapseSeconds);
            }
        }

        /// <summary>
        /// 关闭并清理实体管理器。
        /// </summary>

View on GitHub (pinned to d0c010b051)