egametang/ET · error · Exception

entity is disposed, instanceid == 0!

Error message

entity is disposed, instanceid == 0!

What it means

Thrown by the EntityRef<T> constructor when wrapping an entity whose InstanceId is 0. InstanceId==0 means the entity has been disposed (or never registered). Holding a strong EntityRef to a disposed entity is unsafe, so the constructor rejects it.

Source

Thrown at Packages/cn.etetet.core/Scripts/Core/Share/Entity/EntityRef.cs:65

            return left.Equals(right);
        }

        public static bool operator !=(EntityRef<T> left, EntityRef<T> right)
        {
            return !left.Equals(right);
        }

        private EntityRef(T t)
        {
            if (t == null)
            {
                this.instanceId = 0;
                this.entity = null;
                return;
            }
            if (t.InstanceId == 0)
            {
                throw new Exception("entity is disposed, instanceid == 0!");
            }

            this.instanceId = t.InstanceId;
            this.entity = t;
        }
        
        public T Entity
        {
            get
            {
                if (this.entity == null)
                {
                    return null;
                }
                if (this.entity.InstanceId != this.instanceId)
                {
                    // 这里instanceId变化了,设置为null,解除引用,好让runtime去gc
                    this.entity = null;

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Check `entity != null && entity.InstanceId != 0` before constructing EntityRef.
  2. Do not hold EntityRef across frames without re-validating; prefer weak references for caches.
  3. Ensure Dispose is not called before all outstanding references are dropped.

Example fix

// before
var r = new EntityRef<T>(entity);   // entity may be disposed

// after
if (entity == null || entity.InstanceId == 0)
{
    Log.Error("target entity disposed, skip EntityRef");
    return;
}
var r = new EntityRef<T>(entity);
Defensive patterns

Strategy: type-guard

Validate before calling

if (entity != null && entity.InstanceId != 0)
{
    var r = new EntityRef<T>(entity);
}

Type guard

static bool IsLive<T>(T e) where T : Entity
    => e != null && e.InstanceId != 0;

Prevention

When it happens

Trigger: Constructing EntityRef on an entity after Dispose; capturing a disposed entity into EntityRef; an entity reference obtained from a stale cache whose InstanceId reset to 0 after recycling.

Common situations: Storing EntityRef across an await and the target was disposed meanwhile; pooled entities reused after Dispose (InstanceId reset); event handlers firing with a disposed sender.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/81ae78ceeb24049e. Report an issue: GitHub.