XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Full type name for is ; Any message's type url is

Error message

Full type name for {target.Descriptor.Name} is {target.Descriptor.FullName}; Any message's type url is {TypeUrl}

What it means

Any.Unpack<T> validates that the type URL embedded in the Any message matches T's full protobuf type name (after stripping the leading host '/'). A mismatch throws InvalidProtocolBufferException because the stored bytes cannot be safely interpreted as T. This guards against decoding an Any payload into the wrong message type.

Solutions

  1. Unpack to the correct type: match T to the actual type name in any.TypeUrl (inspect it before unpacking).
  2. Use Any.GetTypeName(TypeUrl) and compare with target descriptor full names to select the right type at runtime.
  3. Fix schema drift: regenerate/align type names (package path) between producer and consumer, or migrate stored data.
  4. If types are equivalent but names differ, re-pack with the canonical name: Any.Pack(correctMessage).

Example fix

// before
var req = any.Unpack<CreateUserRequest>(); // throws if any holds a different type
// after
if (Any.GetTypeName(any.TypeUrl) == CreateUserRequest.Descriptor.FullName)
    var req = any.Unpack<CreateUserRequest>();
else
    /* handle unexpected type */;
Defensive patterns

Strategy: validation

Validate before calling

if (Any.GetTypeName(any.TypeUrl) != typeof(T).Name &&
    Any.GetTypeName(any.TypeUrl) != T.Descriptor.FullName)
{
    throw new InvalidOperationException($"Any holds {any.TypeUrl}, not {T.Descriptor.FullName}");
}
var msg = any.Unpack<T>();

Type guard

bool CanUnpack<T>(Any any) where T : IMessage<T> => Any.GetTypeName(any.TypeUrl) == T.Descriptor.FullName;

Try / catch

try { return any.Unpack<T>(); } catch (InvalidProtocolBufferException ex) when (ex.Message.Contains("type url")) { log.Warn($"Any type mismatch: {ex.Message}"); return null; }

Prevention

When it happens

Trigger: Calling any.Unpack<T>() where the Any was created from a different message type, where TypeUrl uses a different type name casing/namespace, or where the Any came from a service using a different package version of the type.

Common situations: Type renamed/moved between packages in a schema refactor so old stored Anys no longer match new type names; cross-service mismatches where producer and consumer disagree on the packed type; forgetting that Unpack<T> is strict while UnpackTo on an unknown Any is a different flow.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/WellKnownTypes/AnyPartial.cs:79

            int lastSlash = typeUrl.LastIndexOf('/');
            return lastSlash == -1 ? "" : typeUrl.Substring(lastSlash + 1);
        }

        /// <summary>
        /// Unpacks the content of this Any message into the target message type,
        /// which must match the type URL within this Any message.
        /// </summary>
        /// <typeparam name="T">The type of message to unpack the content into.</typeparam>
        /// <returns>The unpacked message.</returns>
        /// <exception cref="InvalidProtocolBufferException">The target message type doesn't match the type URL in this message</exception>
        public T Unpack<T>() where T : IMessage, new()
        {
            // Note: this doesn't perform as well is it might. We could take a MessageParser<T> in an alternative overload,
            // which would be expected to perform slightly better... although the difference is likely to be negligible.
            T target = new T();
            if (GetTypeName(TypeUrl) != target.Descriptor.FullName)
            {
                throw new InvalidProtocolBufferException("Full type name for " + target.Descriptor.Name + " is " + target.Descriptor.FullName + "; Any message's type url is " + TypeUrl);
            }
            target.MergeFrom(Value);
            return target;
        }

        /// <summary>
        /// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com".
        /// </summary>
        /// <param name="message">The message to pack.</param>
        /// <returns>An Any message with the content and type URL of <paramref name="message"/>.</returns>
        public static Any Pack(IMessage message)
        {
            return Pack(message, DefaultPrefix);
        }

        /// <summary>
        /// Packs the specified message into an Any message using the specified type URL prefix.
        /// </summary>

View on GitHub (pinned to 016f98412e)