Skip to content

Keep known fields with a mismatched wire type as unknown fields - #454

Closed
lukaszsamson wants to merge 1 commit into
elixir-protobuf:mainfrom
lukaszsamson:decode-wrong-wire-type-as-unknown
Closed

lukaszsamson wants to merge 1 commit into
elixir-protobuf:mainfrom
lukaszsamson:decode-wrong-wire-type-as-unknown

Conversation

@lukaszsamson

@lukaszsamson lukaszsamson commented Oct 9, 2026 •

Copy link
Copy Markdown

Closes #453.

When a known field arrives with a wire type other than the one its type uses, the decoder raises Protobuf.DecodeError ("wrong wire_type for field ...") and the whole message fails. Go, Java, C++ and upb keep such a field as an unknown field and keep decoding; #453 has permalinks to each implementation.

Changes

  • Protobuf.Decoder.handle_value/7: remove the raising clause. A known field whose wire type matches none of the clauses now falls through to the existing unknown-field handling. The value has already been consumed according to its own wire type, so the rest of the message decodes normally. The bytes go into __unknown_fields__, so re-encoding is byte-identical.
  • Only take the packed path for a packed? field when the value is length-delimited. Previously a packed field arriving as fixed32/fixed64 was decoded as if it were packed data, which produced garbage values. Packed fields still accept the unpacked encoding through the regular wire_type: ^wire_type clause.
  • Tests:
    • replace "raises for wrong wire type" with cases covering scalar, string, embedded-message, packed and map-entry fields;
    • check that later fields still decode;
    • check that encode(decode(bin)) == bin.
  • CHANGELOG entry under Unreleased.

mix test: 646 passed (2 skipped, 9 excluded). mix format --check-formatted is clean.

I also checked it end to end on the real payload from the issue: a TRON Nile BlockListExtention containing a tx whose Transaction.Contract.provider (bytes) is a varint. It decodes with the unmodified schema, the field lands in __unknown_fields__, and all 12 transaction hashes recomputed from the re-encoded Transaction.raw match their txids.

I didn't run the conformance runner locally. The ValidDataMap.*.WireTypeMismatch tests (RECOMMENDED) accept output equal to the C++ reference, which drops the unknown entry field and uses the default value; the new map-entry test asserts that result.

🤖 Generated with Claude Code

When a known field arrives with a wire type other than the one its type
uses, the decoder raised Protobuf.DecodeError ("wrong wire_type for
field ..."), failing the whole message. The reference implementations
(C++, Java, Go, upb) instead keep such a field as an unknown field and
continue decoding. Do the same: fall through to the unknown-field
clause, which preserves the bytes in __unknown_fields__ so re-encoding
is byte-identical.

Also only take the packed path for a packed? field when the value is
length-delimited. Previously a packed field arriving as fixed32/fixed64
was decoded as if it were packed data, yielding garbage values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@whatyouhide

Copy link
Copy Markdown
Collaborator

@lukaszsamson I'm sorry but I’m not gonna accept patches that are generated with Claude and where the author didn't even take the time to tell me (as human to human) the point of the patch (other than linking to another AI generate issue). I have access to coding agents too so might as well throw one at this myself. Thanks!

@whatyouhide whatyouhide closed this Oct 9, 2026
@lukaszsamson

Copy link
Copy Markdown
Author

@whatyouhide sorry for the clanker PR. Would you like a human made one? I do believe the patch is warranted and it solves a real problem. Alternatives I have are forking the lib, migrating to something else or hand hacking the generated stubs

@whatyouhide

Copy link
Copy Markdown
Collaborator

I’m happy to review something from you. If a robot writes the code I have zero issues but I’m not going to read slop (in PR descriptions or code comments or documentation) 🙃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Known field with a mismatched wire type raises DecodeError; reference implementations keep it as an unknown field

2 participants