XINCGer/Unity3DTraining · error · InvalidOperationException

Invalid type argument requested for wrapper codec:

Error message

Invalid type argument requested for wrapper codec: 

What it means

WrapperFieldCodec.GetCodec<T> throws InvalidOperationException when T is not one of the supported wrapper value types registered in its static Codecs table. Only the protobuf primitive wrapper value types (e.g. Int32Value, StringValue, BoolValue, BytesValue) have codecs.

Solutions

  1. Use the corresponding wrapper message type (Int32Value, Int64Value, UInt32Value, UInt64Value, FloatValue, DoubleValue, BoolValue, StringValue, BytesValue) as T
  2. Use the generated code's built-in codec instead of hand-constructing one
  3. Wrap the raw value in the wrapper type before creating the codec
  4. Regenerate code with matching Google.Protobuf runtime version

Example fix

// before
var codec = FieldCodec.Wrap<int>();
// after
var codec = FieldCodec.Wrap<Int32Value>();
Defensive patterns

Strategy: type-guard

Validate before calling

bool isWrapper = typeof(T) == typeof(Int32Value) || typeof(T) == typeof(Int64Value) || typeof(T) == typeof(UInt32Value) || typeof(T) == typeof(UInt64Value) || typeof(T) == typeof(FloatValue) || typeof(T) == typeof(DoubleValue) || typeof(T) == typeof(BoolValue) || typeof(T) == typeof(StringValue) || typeof(T) == typeof(BytesValue);

Type guard

static bool IsWrapperType(Type t) => typeof(IMessage).IsAssignableFrom(t) && t.FullName.StartsWith("Google.Protobuf.WellKnownTypes.") && t.Name.EndsWith("Value");

Try / catch

try { return FieldCodec.Wrap<T>(); } catch (InvalidOperationException) { throw new NotSupportedException($"{typeof(T)} is not a wrapper value type"); }

Prevention

When it happens

Trigger: Calling FieldCodec.Wrap<T> (GetCodec<T>) with a type argument that is not a Google.Protobuf.WellKnownTypes wrapper message, e.g. GetCodec<int> or a custom message type.

Common situations: Hand-writing FieldCodec instances for map/repeated wrapper fields with the wrong generic parameter; code generation mismatch between proto syntax (proto2 optional scalars) and runtime; reflection-driven code building codecs by Type.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/dc647e8a4d34c076. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/FieldCodec.cs:288

                { typeof(long), ForInt64(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
                { typeof(uint), ForUInt32(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
                { typeof(ulong), ForUInt64(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) },
                { typeof(float), ForFloat(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Fixed32)) },
                { typeof(double), ForDouble(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Fixed64)) },
                { typeof(string), ForString(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) },
                { typeof(ByteString), ForBytes(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }
            };

            /// <summary>
            /// Returns a field codec which effectively wraps a value of type T in a message.
            /// 
            /// </summary>
            internal static FieldCodec<T> GetCodec<T>()
            {
                object value;
                if (!Codecs.TryGetValue(typeof(T), out value))
                {
                    throw new InvalidOperationException("Invalid type argument requested for wrapper codec: " + typeof(T));
                }
                return (FieldCodec<T>)value;
            }

            internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec)
            {
                int length = input.ReadLength();
                int oldLimit = input.PushLimit(length);

                uint tag;
                T value = codec.DefaultValue;
                while ((tag = input.ReadTag()) != 0)
                {
                    if (tag == codec.Tag)
                    {
                        value = codec.Read(input);
                    }
                    else

View on GitHub (pinned to 016f98412e)