openzipkin/zipkin · error · IllegalArgumentException
Greater than 64-bit varint at position {}
Error message
Greater than 64-bit varint at position {} What it means
ReadBuffer.readVarint64 accepts at most 10 bytes; on the 10th byte any value bits above the low 4 ((b & 0xf0) != 0) mean the number exceeds 64 bits, and it throws 'Greater than 64-bit varint at position P'. Real protobuf never produces this; it indicates corrupt bytes or a stream that lost field alignment.
Source
Thrown at zipkin/src/main/java/zipkin2/internal/ReadBuffer.java:366
b = readByte();
if ((b & 0xf0) != 0) {
throw new IllegalArgumentException("Greater than 32-bit varint at position " + (pos() - 1));
}
return result | b << 28;
}
final long readVarint64() {
byte b; // negative number implies MSB set
if ((b = readByte()) >= 0) {
return b;
}
long result = b & 0x7f;
for (int i = 1; b < 0 && i < 10; i++) {
b = readByte();
if (i == 9 && (b & 0xf0) != 0) {
throw new IllegalArgumentException("Greater than 64-bit varint at position " + (pos() - 1));
}
result |= (long) (b & 0x7f) << (i * 7);
}
return result;
}
final void require(int byteCount) {
if (this.available() < byteCount) {
throw new IllegalArgumentException(
"Truncated: length " + byteCount + " > bytes available " + this.available());
}
}
int checkReadArguments(byte[] dst, int offset, int length) {
if (dst == null) throw new NullPointerException();
if (offset < 0 || length < 0 || length > dst.length - offset) {
throw new IndexOutOfBoundsException();
}View on GitHub (pinned to 878ce2a1fa)
Solutions
- Use the reported position to verify alignment: check that the preceding tag and length prefix were parsed correctly.
- Run the payload through protoc --decode (proto3) or a thrift inspector to find the first structural error.
- Fix the upstream corruption (double-encoding, wrong charset, truncation) rather than the decoder.
- In collectors, isolate bad messages to a dead-letter path and continue.
Example fix
// before
// fed arbitrary bytes straight into the decoder
Span span = SpanBytesDecoder.PROTO3.decodeOne(downloadBytes(url));
// after
byte[] bytes = downloadBytes(url);
// validate the magic shape first (field 1, length-delimited) then decode
if (bytes.length < 2 || bytes[0] != 0x0a) throw new IllegalArgumentException("not a zipkin proto3 span");
Span span = SpanBytesDecoder.PROTO3.decodeOne(bytes); Defensive patterns
Strategy: try-catch
Try / catch
catch (IllegalArgumentException e) { if (e.getMessage().contains("64-bit varint")) { quarantine(bytes); return Optional.empty(); } throw e; } Prevention
- Detect >10-byte varint runs only happens with corruption — suspect alignment, not values.
- Dead-letter malformed transport messages instead of retrying them.
When it happens
Trigger: Decoding a 64-bit varint field (timestamps, trace ID high bits, duration in thrift) where continuation bytes run past the 10-byte limit — typically because the reader started mid-field on garbage bytes.
Common situations: Misaligned reads after skipping an unknown field with a bad length; payloads that are not protobuf/thrift at all; storage blobs with flipped high bits (bit rot, bad base64 decoding).
Related errors
- Greater than 32-bit varint at position {}
- Malformed: fieldNumber was zero at byte
- Malformed: invalid wireType
- Malformed: invalid boolean value at byte
- hex field greater than 32 chars long: {}
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/e7e8791b579dd92b.
Report an issue: GitHub.