egametang/ET · error · Exception

[PreservedMethod] method:{methodDef} has generic parameters

Error message

[PreservedMethod] method:{methodDef} has generic parameters

What it means

Thrown by Generator.CreateMethodDesc (the overload taking a MethodDef) when the method's return type ContainsGenericParameter. The method bridge generator requires fully concrete type signatures to emit bridge/wrapper functions; an open generic parameter on the return type means the signature was never inflated to a concrete type.

Source

Thrown at Packages/cn.etetet.hybridclr/Scripts/Editor/Share/MethodBridge/Generator.cs:124

            string sigName = ToFullName(typeInfo.Klass);
            if (!_sig2Types.TryGetValue(sigName, out var sharedTypeInfo))
            {
                sharedTypeInfo = typeInfo;
                _sig2Types.Add(sigName, sharedTypeInfo);
            }
            return sharedTypeInfo;
        }

        private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)
        {
            var paramInfos = new List<ParamInfo>();
            if (forceRemoveThis && !methodDef.IsStatic)
            {
                parameters.RemoveAt(0);
            }
            if (returnType.ContainsGenericParameter)
            {
                throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters");
            }
            foreach (var paramInfo in parameters)
            {
                if (paramInfo.ContainsGenericParameter)
                {
                    throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters");
                }
                paramInfos.Add(new ParamInfo() { Type = GetSharedTypeInfo(paramInfo) });
            }
            var mbs = new MethodDesc()
            {
                MethodDef = methodDef,
                ReturnInfo = new ReturnInfo() { Type = returnType != null ? GetSharedTypeInfo(returnType) : TypeInfo.s_void },
                ParamInfos = paramInfos,
            };
            return mbs;
        }

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Ensure all generic method instantiations used across the AOT/hot-update boundary are captured by HybridCLR/Generate/AOTGenericReference first.
  2. If a method is annotated [PreservedMethod] or [MonoPInvokeCallback], make sure it is non-generic or only used with concrete instantiations.
  3. Re-run HybridCLR/Generate/All to regenerate bridge functions with the latest generic reference data.
  4. Inspect the methodDef printed in the exception and refactor it to avoid open generic parameters at the bridge boundary.
Defensive patterns

Strategy: validation

Validate before calling

// Before bridge generation, ensure no preserved method has open generics
if (returnType.ContainsGenericParameter)
    Debug.LogError("Method return type has open generic -- inflate or avoid bridging.");

Prevention

When it happens

Trigger: CreateMethodDesc(methodDef, forceRemoveThis, returnType, parameters) is called with a returnType whose ContainsGenericParameter is true. This happens when ProcessMethod passed through a method whose generic arguments were not substituted (klassInst/methodInst both null but the method still carries open generics).

Common situations: A preserved method (annotated or referenced via reverse P/Invoke) is itself generic and was not instantiated before bridge generation; the AOT generic reference pass missed an instantiation; a code change introduced a generic method signature that HybridCLR cannot bridge.

Related errors


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