EllanJiang/GameFramework · error · GameFrameworkException

Object ' ' spawn count is less than 0.

Error message

Object '{0}' spawn count is less than 0.

What it means

Each pooled Object<T> tracks a spawn count incremented on Spawn and decremented on Unspawn. If Unspawn is called more times than Spawn, the count would go negative, indicating unbalanced bookkeeping, so it throws. This is an internal invariant check protecting the pool's reference counting.

Solutions

  1. Only Unspawn objects obtained from objectPool.Spawn, exactly once per Spawn
  2. Track ownership of the spawn reference in your code; guard with CanSpawn/HasObject checks where available
  3. Audit error paths for duplicated Unspawn calls (remove one from handler/finally)

Example fix

// before
finally { pool.Unspawn(obj); }
catch { pool.Unspawn(obj); } // unspawns twice on error
// after
catch { /* log only */ }
finally { pool.Unspawn(obj); }
Defensive patterns

Strategy: validation

Validate before calling

if (pool.HasObject(obj.Name) && /* you hold a spawn reference */ ownsSpawn) pool.Unspawn(obj);

Type guard

bool CanUnspawn(ObjectInfo info) => info != null && info.SpawnCount > 0;

Try / catch

try { pool.Unspawn(obj); }
catch (GameFrameworkException ex) { Log.Error("Unspawn without matching Spawn for '{0}'", obj.Name); }

Prevention

When it happens

Trigger: Calling objectPool.Unspawn(obj) on an object that was never spawned, or unspawning the same object twice; also calling Unspawn after SetLock/lock-release cycles that reset spawn state.

Common situations: Double-unspawn in error/cleanup paths (e.g. unspawning in both a failure handler and a finally block); unspawning objects created directly rather than via Spawn; mismatched Spawn/Unspawn after exception in between.

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/551744d7626fd356. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/ObjectPool/ObjectPoolManager.Object.cs:181

            public T Spawn()
            {
                m_SpawnCount++;
                m_Object.LastUseTime = DateTime.UtcNow;
                m_Object.OnSpawn();
                return m_Object;
            }

            /// <summary>
            /// 回收对象。
            /// </summary>
            public void Unspawn()
            {
                m_Object.OnUnspawn();
                m_Object.LastUseTime = DateTime.UtcNow;
                m_SpawnCount--;
                if (m_SpawnCount < 0)
                {
                    throw new GameFrameworkException(Utility.Text.Format("Object '{0}' spawn count is less than 0.", Name));
                }
            }

            /// <summary>
            /// 释放对象。
            /// </summary>
            /// <param name="isShutdown">是否是关闭对象池时触发。</param>
            public void Release(bool isShutdown)
            {
                m_Object.Release(isShutdown);
                ReferencePool.Release(m_Object);
            }
        }
    }
}

View on GitHub (pinned to d0c010b051)