egametang/ET · critical · Exception
OpcodeType not found opcode: {type.FullName}
Error message
OpcodeType not found opcode: {type.FullName} What it means
OpcodeType.GetOpcode(Type) returns the registered opcode for a message type; a value of 0 means the type was never registered. The framework treats unregistered messages as a fatal serialization contract error.
Source
Thrown at Packages/cn.etetet.core/Scripts/Core/Share/Network/OpcodeType.cs:64
var attrs = type.GetCustomAttributes(typeof (ResponseTypeAttribute), false);
if (attrs.Length == 0)
{
Log.Error($"not found responseType: {type}");
continue;
}
ResponseTypeAttribute responseTypeAttribute = attrs[0] as ResponseTypeAttribute;
this.requestResponse.Add(type, CodeTypes.Instance.GetType($"ET.{responseTypeAttribute.Type}"));
}
}
}
public ushort GetOpcode(Type type)
{
ushort opcode = this.typeOpcode.GetValueByKey(type);
if (opcode == 0)
{
throw new Exception($"OpcodeType not found opcode: {type.FullName}");
}
return opcode;
}
public Type GetType(ushort opcode)
{
Type type = this.typeOpcode.GetKeyByValue(opcode);
if (type == null)
{
throw new Exception($"OpcodeType not found type: {opcode}");
}
return type;
}
public Type GetResponseType(Type request)
{
if (!this.requestResponse.TryGetValue(request, out Type response))
{View on GitHub (pinned to 5cab01f7a8)
Solutions
- Confirm the type has the message attribute and is in a scanned assembly.
- Re-run the Luban/opcode code generation so the opcode table includes the type.
- Ensure the message assembly is loaded before OpcodeType initialization.
Example fix
// before ushort op = OpcodeType.Instance.GetOpcode(typeof(MyNewMessage)); // after // add [Message(...)]; regenerate opcodes; then: ushort op = OpcodeType.Instance.GetOpcode(typeof(MyNewMessage));
Defensive patterns
Strategy: validation
Validate before calling
if (!OpcodeType.Instance.IsRegistered(type)) throw new InvalidOperationException($"{type} has no opcode; regenerate protocol");
ushort op = OpcodeType.Instance.GetOpcode(type); Type guard
public bool IsRegistered(Type t) => typeOpcode.ContainsKey(t);
Try / catch
null
Prevention
- Add message attributes when you add a message class.
- Regenerate opcodes and load the right assemblies at init.
- Unit-test that every sent type has a registered opcode.
When it happens
Trigger: Sending a message Type that was not scanned by CodeTypes or lacks the message/protocol attributes, or sending a type from an assembly that wasn't loaded at registration time.
Common situations: New message class added without [Message]/[ProtoContract] attribute, the assembly not passed to CodeTypes, or hotfix code referencing a type compiled out of the opcode generation.
Related errors
- OpcodeType not found type: {opcode}
- not found response type, request type: {request.FullName}
- 不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}
- {runtimeType.FullName} 缺少可用于导出的公共构造函数。必须通过构造函数提供的成员: {names}
- 无法为类型 {type.FullName} 生成稳定排序键
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/0bd4c89736adfa49.
Report an issue: GitHub.