proto:无法解析无效的 wire-format 数据
proto: cannot parse invalid wire-format data
ID: go/proto-unmarshal-cannot-parse-invalid-wire-format
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| google.golang.org/protobuf 1.28+ | active | — | — | — |
根因分析
proto.Unmarshal 收到的字节对于目标消息类型不是有效的 protobuf wire format。典型原因:负载是 JSON/纯文本、被截断、是另一种消息类型,或某个长度分隔字段的 varint 长度前缀已损坏。
English
proto.Unmarshal received bytes that are not valid protobuf wire format for the target message type. Typical causes: the payload is JSON/plain text, it was truncated, it's a different message type, or a length-delimited field has a corrupt varint length prefix.
解决方案
-
85% 成功率
Validate and log the raw bytes before unmarshaling, and confirm the wire type matches: if len(data) == 0 { return errors.New("empty payload") } if err := proto.Unmarshal(data, msg); err != nil { log.Printf("unmarshal failed, first 32 bytes: %x", data[:min(32,len(data))]) return fmt.Errorf("bad proto payload: %w", err) } -
80% 成功率
Ensure the sender and receiver use the same generated message and that framing (length prefix) is stripped correctly, e.g. with a length-delimited reader: r := protoio.NewDelimitedReader(conn, 1<<20) msg := &pb.Foo{} if err := r.ReadMsg(msg); err != nil { return err }
无效尝试
常见但无效的做法:
-
98% 失败
Wire-format parsing is deterministic; identical bytes always fail identically. Retrying wastes CPU and never succeeds.
-
75% 失败
If the bytes are binary protobuf, protojson will reject them; if they are JSON, the original proto.Unmarshal was simply the wrong parser choice — the fix is picking the right one, not blindly swapping.