openzipkin/zipkin · error · IllegalArgumentException
Malformed: invalid wireType
Error message
Malformed: invalid wireType
What it means
A protobuf tag's low 3 bits encode the wire type; only values 0 (varint), 1 (64-bit), 2 (length-delimited), 5 (32-bit) are legal in Zipkin's reader (groups 3/7 are unused/obsolete). Proto3Fields.Field.wireType throws 'Malformed: invalid wireType N at byte P' when the key decodes to wire type 3, 4, 6, or 7, meaning the stream is corrupt or not protobuf.
Source
Thrown at zipkin/src/main/java/zipkin2/internal/Proto3Fields.java:58
this(key >>> 3, key & (1 << 3) - 1, key);
}
Field(int fieldNumber, int wireType, int key) {
this.fieldNumber = fieldNumber;
this.wireType = wireType;
this.key = key;
}
static int fieldNumber(int key, int byteL) {
int fieldNumber = key >>> 3;
if (fieldNumber != 0) return fieldNumber;
throw new IllegalArgumentException("Malformed: fieldNumber was zero at byte " + byteL);
}
static int wireType(int key, int byteL) {
int wireType = key & (1 << 3) - 1;
if (wireType != 0 && wireType != 1 && wireType != 2 && wireType != 5) {
throw new IllegalArgumentException(
"Malformed: invalid wireType " + wireType + " at byte " + byteL);
}
return wireType;
}
static boolean skipValue(ReadBuffer buffer, int wireType) {
int remaining = buffer.available();
switch (wireType) {
case WIRETYPE_VARINT:
for (int i = 0; i < remaining; i++) {
if (buffer.readByte() >= 0) return true;
}
return false;
case WIRETYPE_FIXED64:
return buffer.skip(8) == 8;
case WIRETYPE_LENGTH_DELIMITED:
int length = buffer.readVarint32();
return buffer.skip(length) == length;View on GitHub (pinned to 878ce2a1fa)
Solutions
- Use the reported byte offset to hex-dump the region and confirm whether the stream is proto3 at all.
- Check the preceding field's length prefix for off-by-one bugs in any custom encoding path.
- Send the payload through a reference protobuf parser (protoc --decode with zipkin2.proto) to locate the first invalid tag.
- Fix the producer to use SpanBytesEncoder.PROTO3 instead of hand-rolled serialization.
Example fix
// before // custom hand-rolled encoder wrote field key 0x1d (wireType 5) for a string // after // use the shipped codec so tags are always well-formed byte[] bytes = SpanBytesEncoder.PROTO3.encode(span);
Defensive patterns
Strategy: try-catch
Try / catch
try { decode(bytes); } catch (IllegalArgumentException e) { if (e.getMessage().contains("invalid wireType")) { quarantine(bytes); return List.of(); } throw e; } Prevention
- Validate payloads with protoc --decode in a pre-prod stage.
- Avoid concatenating encodings; use one message per queue item.
- Add checksums (CRC32) over span blobs on internal transports.
When it happens
Trigger: PROTO3 span decoding hits a tag whose key & 0x7 yields an illegal value — usually the reader is misaligned (after a bad length or truncated varint) or the bytes are another format entirely.
Common situations: Non-proto bytes fed to the proto3 decoder; a producer writing wrong varint tags; corrupted blobs in storage; concatenating two encodings without proper framing.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed: fieldNumber was zero at byte
- Malformed: invalid boolean value at byte
- hex field greater than 32 chars long: {}
- Greater than 32-bit varint at position {}
- Greater than 64-bit varint at position {}
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/5a3db77e15020eba.
Report an issue: GitHub.