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

  1. Use the reported position to verify alignment: check that the preceding tag and length prefix were parsed correctly.
  2. Run the payload through protoc --decode (proto3) or a thrift inspector to find the first structural error.
  3. Fix the upstream corruption (double-encoding, wrong charset, truncation) rather than the decoder.
  4. 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

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


AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14). Data as JSON: /api/errors/e7e8791b579dd92b. Report an issue: GitHub.