ErrLookup › Background articles › "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained
"cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained
Protobuf unmarshal errors appear when bytes passed to a protobuf decoder (proto.Unmarshal, protoutil.Unmarshal, easyproto, gogo/protobuf) are not a valid encoding of the expected message — corrupted, truncated, empty, or produced from a different schema. Developers hit them as messages like "cannot unmarshal point", "failed unmarshalling payload", "error unmarshalling Envelope", "illegal tag", or "wiretype end group for non-group" from libraries such as VictoriaMetrics, Hyperledger Fabric, Teleport, rqlite, and Pulumi.
Distilled from 144 documented records across 10 repositories.
Background
This error family lives at the boundary between raw bytes and structured data. Every protobuf library — google.golang.org/protobuf, gogo/protobuf, easyproto, protoutil wrappers — walks the wire format one field at a time: it reads a tag varint (field number plus wire type), then the payload for that wire type. The decoder fails the moment the stream stops making sense: a tag with wire type 4 (end-group) where no group was opened (Teleport's "wiretype end group for non-group" on the Passwordless message), a field number <= 0 or an unknown field whose skip logic also fails ("illegal tag %d (wire type %d)"), a length-delimited field whose length exceeds the remaining bytes, or a nested MessageData() call that cannot extract the declared submessage (VictoriaMetrics' easyproto-based "cannot read Sketch data"). The decoder has no schema knowledge beyond the message it is filling, so any deviation from valid wire format — not just a wrong field value — is fatal.
Critically, the wire format is untyped at the top: the decoder fills whatever message struct you hand it. That means these errors usually do not mean "bad field value"; they mean the bytes were never a serialization of the expected message at all. The recurring patterns across the records are: (1) truncation — a request cut off mid-frame by a proxy, a Content-Length mismatch, a partial TCP read, or a truncated block on disk (Fabric's "error unmarshalling Envelope" from block Data, rqlite's "protobuf unmarshal" on the cluster mux); (2) wrong bytes entirely — an HTTP 200 body that is actually HTML or JSON being decoded as protobuf (7days-golang's "decoding response body"), gzip or snappy not decompressed before decoding, base64 still applied, or bytes of a different message type placed in a slot (a SignatureHeader marshaled into a ChannelHeader slot, an Idemix MSPConfig passed to a FABRIC-type MSP); and (3) schema or version skew between producer and consumer — sender and receiver built from different .proto definitions, so field numbers or shapes diverge (rqlite nodes on incompatible versions, Fabric SDKs and peers on mismatched fabric-protos).
From the caller's side the error usually arrives wrapped: the library adds context about which decode step failed and which message was expected, while the underlying cause carries the protobuf-level detail. Some wrappers include the payload size (VictoriaMetrics' prompb WriteRequest error reports the byte count, which immediately distinguishes an empty body from a huge truncated one); others include a transaction ID (Fabric's "failed to unmarshal response for transaction %s"); others use a %w chain the caller must unwrap to see the real cause. Fabric alone contributes a dozen variants, each naming the exact message that failed to decode — Envelope, Payload, Proposal, ChannelHeader, MSPRole, MSPConfig, CollectionConfigPackage, ChaincodeData — because its architecture unmarshals protobuf at many trust boundaries (block parsing, transaction validation, policy evaluation, MSP setup, discovery), so corruption at any boundary produces a distinct message but the same root mechanism.
A few behaviors are library-specific. VictoriaMetrics uses hand-rolled easyproto decoding, so it fails early and precisely at each field ("cannot read next field in Sketch message") and expects callers to check wire types (field 1 must be wire type 2, length-delimited). Fabric's *OrPanic variants (UnmarshalConfigOrPanic) panic instead of returning an error, treating decode failure as a programmer error or corrupted internal data. Teleport's gogo-generated code surfaces raw generated-decoder messages like "illegal tag" that reference the message name and wire types directly. rqlite decodes over a raw TCP mux, so a misrouted port or HTTP-aware proxy produces the same unmarshal failure as true corruption.
Common causes
- Truncated or incomplete payload. A proxy, timeout handler, or partial read cut the body off mid-message, or a length prefix exceeds the remaining bytes. Fabric sees this with block/ledger data on disk; VictoriaMetrics sees it with partial HTTP uploads; rqlite sees it on the TCP mux stream.
- Bytes are not protobuf at all. A 200 response body that is actually HTML/JSON (7days-golang pointing at a non-peer endpoint), an undecoded gzip or snappy body, base64 text, or a hand-built byte slice fed directly to the decoder. The decoder rejects it at the first invalid tag.
- Wrong message type or wrong slot. Valid protobuf bytes of a different message decoded as the expected one — a SignatureHeader in the ChannelHeader slot, envelope bytes passed to UnmarshalConfig, an Idemix MSPConfig given to a FABRIC-type MSP, or a scalar where a length-delimited submessage is declared (VictoriaMetrics field 1 wire type mismatch).
- Schema or version skew between producer and consumer. Sender and receiver were built from different .proto versions, so field numbers, wire types, or message shapes diverge. The records repeatedly call for pinning fabric-protos, agent-payload, or pulumirpc versions in lockstep across components.
- Hand-crafted or incorrectly serialized messages. Application code assembles protobuf fields manually — raw strings where a marshaled MSPRole belongs, hand-built COMPLETED chaincode messages, or manually assembled Fabric envelopes — instead of using the official marshal helpers and SDK builders.
- Corrupted stored data or transport. Bits flipped in storage or transit: truncated Fabric blocks, corrupt ledger state entries under the lscc namespace, bad block metadata, or a middlebox altering an inter-node TCP stream. Disk/filesystem corruption shows up as unmarshal failures at ledger open time.
- Empty or nil input treated as decodable. An empty Payload, a nil Extension, or a missing config value is handed to Unmarshal and fails. Several Fabric records (empty ProposalBytes, empty MSP config value) specifically recommend logging byte lengths so zero-length inputs are caught before decoding.
What usually fixes it
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
Go deeper
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Documented occurrences
- cannot read Sketch data (VictoriaMetrics/VictoriaMetrics)
- failed to unmarshal response for transaction %s (hyperledger/fabric)
- Failing extracting proposal during channelless check policy with policy [%s]: [%s] (hyperledger/fabric)
- could not unmarshal MSPRole from principal (hyperledger/fabric)
- protobuf unmarshal: %w (rqlite/rqlite)
- failed parsing MSPConfig (hyperledger/fabric)
- cannot unmarshal point: %w (VictoriaMetrics/VictoriaMetrics)
- unmarshaling response: %w (pulumi/pulumi)
- proto: Passwordless: wiretype end group for non-group (gravitational/teleport)
- decoding response body: %v (geektutu/7days-golang)
- error unmarshalling ChaincodeHeaderExtension (hyperledger/fabric)
- invalid collection configuration supplied for chaincode %s:%s (hyperledger/fabric)
- failed marshaling FabricMSPConfig (hyperledger/fabric)
- failed unmarshalling payload (hyperledger/fabric)
- failed unmarshalling envelope of config block (hyperledger/fabric)
- Cannot read channels list response, %s (hyperledger/fabric)
- error converting envelope to config update: %s (hyperledger/fabric)
- panic(err) (hyperledger/fabric)
- channel header unmarshalling error: %s (hyperledger/fabric)
- error unmarshalling Envelope (hyperledger/fabric)
…and 124 more across the corpus — use search.
Honest provenance: generated on 2026-09-04 from AI-assisted analysis of the linked records. See how records are made.