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
- Rename one of the two colliding LSEntity types listed in the error to a different FullName to break the hash collision.
- If renaming is not feasible, check the GetLongHashCode implementation for a weak hash function and improve it.
- 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
- Run a hash collision check in the editor/build pipeline for all LSEntity types.
- Avoid creating LSEntity subclasses with similar full names across namespaces.
- If GetLongHashCode has a weak algorithm, improve it to reduce collision probability.
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
- location proxy message sender is null: {self.Root().Name}
- condition variable registry is not initialized
- cant set parent null: {this.GetType().FullName}
- cant set parent self: {this.GetType().FullName}
- cant set parent because parent iSence is null: {this.GetType
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/beb3c283100a4dd6.
Report an issue: GitHub.