Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid wire-type error in protobuf.net on a new MemoryStream

I'm trying to parse a protobuf message received from an external service. I know that this data is a valid protobuf message, and I know I'm not accidentally mangling it before I send it to the deserializer. Here's my code:

public static T DeserializeFromBytes<T>(byte[] encoded)
{
    MemoryStream stream = new MemoryStream(encoded);
    stream.SetLength(encoded.Length);
    stream.Capacity = encoded.Length;
    T decoded = (T)Serializer.Deserialize<T>(stream);
    stream.Close();
    return decoded;
}

and I'm calling this method like this:

MercuryReply header = ProtobufUtils.DeserializeFromBytes<MercuryReply>(Convert.FromBase64String(metadata[0]));

metadata[0] is a base64 string that includes a protobuf message. A sample looks something like this:

CjRobTovL21ldGFkYXRhL2FsYnVtL2M1MzU3MTA0M2U4ODQ3YjRhODc1YzVlNmZiNmNiZTdmEhp2bmQuc3BvdGlmeS9tZXRhZGF0YS1hbGJ1bSCQAzIYCgpNRC1WZXJzaW9uEgoxMzcwMzc5NTA1Mg8KBk1DLVRUTBIFNjk2MDQyGQoPTUMtQ2FjaGUtUG9saWN5EgZwdWJsaWMyDwoHTUMtRVRhZxIELD8q+Q==

Now, when I run the program, I get an Invalid wire-type error when deserializing. I can't see any reason why this would be happening. Is there something obvious here that I missed?

like image 568
CommunistPancake Avatar asked Oct 27 '25 13:10

CommunistPancake


1 Answers

That usually means either:

  • the binary is not valid (people make a mess of binary all the time; your use of base-64 is perfectly fine, though, if it needs to be stored/transferred as a string)
  • there is a mismatch in the data (for example, field 2 is varint in the data, but is a string in the type)

Based on you binary, I've pieced together that MercuryReply might look something like:

[ProtoContract]
public class MercuryReply
{
    [ProtoMember(1)]
    public string Location { get; set; }
    [ProtoMember(2)]
    public string ContentType { get; set; }
    [ProtoMember(4)]
    public int ResponseStatus { get; set; }
    [ProtoMember(6)]
    public Dictionary<string, string> Headers { get { return headers; } }
    private readonly Dictionary<string, string> headers
        = new Dictionary<string, string>();
}

(the names here are pure guesswork based on what the data looks like; protobuf does not transmit names - only the numeric keys, i.e. 1/2/4/6 in this example)

which works fine when tested with:

static void Main()
{
    var encoded = Convert.FromBase64String("CjRobTovL21ldGFkYXRhL2FsYnVtL2M1MzU3MTA0M2U4ODQ3YjRhODc1YzVlNmZiNmNiZTdmEhp2bmQuc3BvdGlmeS9tZXRhZGF0YS1hbGJ1bSCQAzIYCgpNRC1WZXJzaW9uEgoxMzcwMzc5NTA1Mg8KBk1DLVRUTBIFNjk2MDQyGQoPTUMtQ2FjaGUtUG9saWN5EgZwdWJsaWMyDwoHTUMtRVRhZxIELD8q+Q==");

    MercuryReply header = ProtobufUtils.DeserializeFromBytes<MercuryReply>(encoded);

}

(using your DeserializeFromBytes method)

So: if that isn't working for you, the important two questions are:

  • is that the actual base-64 from your real code at runtime? or is that just what you think it should be in theory?
  • what does your MercuryReply class look like?
like image 192
Marc Gravell Avatar answered Oct 29 '25 02:10

Marc Gravell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!