egametang/ET · critical · Exception

long hash add fail: {type.FullName} {sameHashType.FullName}

Error message

long hash add fail: {type.FullName} {sameHashType.FullName}

What it means

Thrown by LSEntitySystemSingleton during initialization when two LSEntity subclass types produce the same GetLongHashCode() value from their FullName. The dictionary lsEntityTypeLongHashCode cannot hold two keys with the same value, so the Add fails. The inner ArgumentException is caught and re-thrown naming both colliding types. This is a hash collision on type full names.

Source

Thrown at Packages/cn.etetet.lsentity/Scripts/Core/Share/LSEntitySystemSingleton.cs:46

                {
                    oneTypeSystems.ClassType.Add(iSystemType.SystemType());
                }
            }
            
            foreach (var kv in CodeTypes.Instance.GetTypes())
            {
                Type type = kv.Value;
                if (typeof(LSEntity).IsAssignableFrom(type))
                {
                    long hash = type.FullName.GetLongHashCode();
                    try
                    {
                        this.lsEntityTypeLongHashCode.Add(type, type.FullName.GetLongHashCode());
                    }
                    catch (Exception e)
                    {
                        Type sameHashType = this.lsEntityTypeLongHashCode.GetKeyByValue(hash);
                        throw new Exception($"long hash add fail: {type.FullName} {sameHashType.FullName}", e);
                    }
                }
            }
        }
        
        public long GetLongHashCode(Type type)
        {
            return this.lsEntityTypeLongHashCode.GetValueByKey(type);
        }
        
        public TypeSystems.OneTypeSystems GetOneTypeSystems(Type type)
        {
            return this.TypeSystems.GetOneTypeSystems(type);
        }
        
        public void LSRollback(Entity entity)
        {
            if (entity is not ILSRollback)

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Rename one of the two colliding LSEntity types listed in the error to a different FullName to break the hash collision.
  2. If renaming is not feasible, check the GetLongHashCode implementation for a weak hash function and improve it.
  3. Ensure no two LSEntity subclasses share the same FullName across all loaded assemblies (check for duplicate class names in different namespaces that hash-collide).

Example fix

// before: two types collide on GetLongHashCode
namespace ET.Game.A { public class Unit : LSEntity { } }
namespace ET.Game.B { public class Hero : LSEntity { } } // collides
// after: rename to break collision
namespace ET.Game.B { public class BattleHero : LSEntity { } }
Defensive patterns

Strategy: validation

Validate before calling

// At build/editor time, verify no two LSEntity types have colliding LongHashCodes
Dictionary<long, Type> seen = new();
foreach (var kv in CodeTypes.Instance.GetTypes())
{
    Type t = kv.Value;
    if (typeof(LSEntity).IsAssignableFrom(t))
    {
        long hash = t.FullName.GetLongHashCode();
        if (seen.TryGetValue(hash, out Type existing))
            Debug.LogError($"LSEntity hash collision: {t.FullName} vs {existing.FullName}");
        else
            seen[hash] = t;
    }
}

Prevention

When it happens

Trigger: During framework initialization, the system scans all types assignable to LSEntity and computes a long hash from each type's FullName. If two different types have the same hash, the dictionary insert throws. This is extremely rare with a good hash but can happen with specific name combinations.

Common situations: Two LSEntity subclasses have very similar or identical full names in different namespaces. A hash collision occurs by chance (GetLongHashCode returns the same value for two distinct strings). Namespace/type renaming created a collision that wasn't there before.

Related errors


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