openzipkin/zipkin · error · IllegalArgumentException
Could not detect the span format
Error message
Could not detect the span format
What it means
SpanBytesDecoderDetector.detectDecoder(ByteBuffer) sniffs the format from the first byte: values <= 16 mean binary (PROTO3 if the protobuf3 heuristic matches, else Thrift); '[' or '{' mean JSON (v2 if it contains "endpoints"/"tags" fields, else JSON_V1). Anything else throws IllegalArgumentException('Could not detect the span format'). This underlying exception propagates through both decoderForMessage and decoderForListMessage.
Source
Thrown at zipkin/src/main/java/zipkin2/SpanBytesDecoderDetector.java:90
public static BytesDecoder<Span> decoderForListMessage(ByteBuffer spans) {
BytesDecoder<Span> decoder = detectDecoder(spans);
byte first = spans.get(spans.position());
if (first != 12 /* List[ThriftSpan] */
&& first != 11 /* openzipkin/zipkin-reporter-java#133 */
&& !protobuf3(spans) && first != '[') {
throw new IllegalArgumentException("Expected json, proto3 or thrift list encoding");
}
return decoder;
}
/** @throws IllegalArgumentException if the input isn't a json or thrift list or object. */
static BytesDecoder<Span> detectDecoder(ByteBuffer bytes) {
byte first = bytes.get(bytes.position());
if (first <= 16) { // binary format
if (protobuf3(bytes)) return SpanBytesDecoder.PROTO3;
return SpanBytesDecoder.THRIFT; /* the first byte is the TType, in a range 0-16 */
} else if (first != '[' && first != '{') {
throw new IllegalArgumentException("Could not detect the span format");
}
if (contains(bytes, ENDPOINT_FIELD_SUFFIX)) return SpanBytesDecoder.JSON_V2;
if (contains(bytes, TAGS_FIELD)) return SpanBytesDecoder.JSON_V2;
return SpanBytesDecoder.JSON_V1;
}
static boolean contains(ByteBuffer bytes, byte[] subsequence) {
bytes:
for (int i = 0; i < bytes.remaining() - subsequence.length + 1; i++) {
for (int j = 0; j < subsequence.length; j++) {
if (bytes.get(bytes.position() + i + j) != subsequence[j]) {
continue bytes;
}
}
return true;
}
return false;
}View on GitHub (pinned to 878ce2a1fa)
Solutions
- Decompress according to Content-Encoding before calling the detector.
- Reset/duplicate the ByteBuffer (buf.duplicate().position(0)) if it has been read before.
- Verify the producer encodes with one of the supported codecs (THRIFT, JSON_V1, JSON_V2, PROTO3 list forms) and match collector/reporter versions.
Example fix
// before
BytesDecoder<Span> d = SpanBytesDecoderDetector.decoderForListMessage(buf);
// after
if ("gzip".equals(contentEncoding)) body = gunzip(body);
BytesDecoder<Span> d = SpanBytesDecoderDetector.decoderForListMessage(ByteBuffer.wrap(body)); Defensive patterns
Strategy: try-catch
Validate before calling
boolean looksLikeSpanPayload(byte[] p) {
if (p.length == 0) return false;
byte f = p[0];
return f <= 16 || f == '[' || f == '{';
} Try / catch
try {
decoder = SpanBytesDecoderDetector.decoderForListMessage(buf);
} catch (IllegalArgumentException e) {
log.warn("undecodable payload, first byte={}", buf.get(buf.position()));
metrics.incrementMalformed(); // drop, don't crash the consumer
} Prevention
- Handle Content-Encoding before sniffing bytes.
- Duplicate/reset ByteBuffers passed to the detector; never reuse a consumed buffer.
- Add a malformed-payload metric to collectors to catch encoder mismatches early.
When it happens
Trigger: Passing payloads whose first byte is > 16 and not '[' or '{' — e.g. undecompressed gzip (0x1f), protobuf field tags > 16, protobuf base64 text, XML, or an empty/garbage buffer offset.
Common situations: Forgetting to decompress gzip/deflate from reporters before decoding; feeding base64- or text-encoded spans; reusing a ByteBuffer whose position was advanced by prior reads so detection sees the wrong byte; version mismatches between reporter encoder and collector decoder.
Related errors
- Expected json or thrift object, not list encoding
- v2 formats should only be used with list messages
- Expected json, proto3 or thrift list encoding
- should be a 1 to 32 character lower-hex string with no pref
- input is not a list
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/f272fe2aac99571a.
Report an issue: GitHub.