{"record":{"id":"abb03da8e8a24fcc","repo":"openzipkin/zipkin","slug":"greater-than-32-bit-varint-at-position","errorCode":null,"errorMessage":"Greater than 32-bit varint at position {}","messagePattern":"Greater than 32-bit varint at position (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin/src/main/java/zipkin2/internal/ReadBuffer.java","lineNumber":351,"sourceCode":"\n    if ((b = readByte()) >= 0) {\n      return result | b << 7;\n    }\n    result |= (b & 0x7f) << 7;\n\n    if ((b = readByte()) >= 0) {\n      return result | b << 14;\n    }\n    result |= (b & 0x7f) << 14;\n\n    if ((b = readByte()) >= 0) {\n      return result | b << 21;\n    }\n    result |= (b & 0x7f) << 21;\n\n    b = readByte();\n    if ((b & 0xf0) != 0) {\n      throw new IllegalArgumentException(\"Greater than 32-bit varint at position \" + (pos() - 1));\n    }\n    return result | b << 28;\n  }\n\n  final long readVarint64() {\n    byte b; // negative number implies MSB set\n    if ((b = readByte()) >= 0) {\n      return b;\n    }\n\n    long result = b & 0x7f;\n    for (int i = 1; b < 0 && i < 10; i++) {\n      b = readByte();\n      if (i == 9 && (b & 0xf0) != 0) {\n        throw new IllegalArgumentException(\"Greater than 64-bit varint at position \" + (pos() - 1));\n      }\n      result |= (long) (b & 0x7f) << (i * 7);\n    }","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin/src/main/java/zipkin2/internal/ReadBuffer.java#L333-L369","documentation":"ReadBuffer.readVarint32 decodes up to 5 bytes; if the 5th byte still has high bits set beyond the 32-bit range ((b & 0xf0) != 0), it throws 'Greater than 32-bit varint at position P'. This means a 32-bit varint field in the payload was encoded with more than 32 bits of payload — corrupt data or a writer emitting 64-bit varints where 32-bit are expected.","triggerScenarios":"Decoding proto3/thrift span fields like durations, timestamps, or length prefixes where the varint run does not terminate within 5 bytes with value bits only in the low 4 bits of the last byte.","commonSituations":"A hand-rolled encoder always writes 10-byte (64-bit style) varints; a sign-extension bug encoding a negative int as a huge varint; misaligned reads after an earlier bad field.","solutions":["Dump the bytes from the reported position and count the varint's continuation bytes (high bit set) — more than 4 continuations means a bad encoder.","Fix producers to use proper varint32 encoding (7 bits per byte, terminate at 5 bytes); prefer the shipped codecs.","Watch for negative Java ints encoded as unsigned 64-bit varints — mask to 32 bits or use writeVarint64 where appropriate.","Quarantine the message; this failure is deterministic per payload."],"exampleFix":"// before\n// naive: wrote int with 64-bit-style 10-byte varint\nlong v = someInt;\nwhile ((v & ~0x7fL) != 0) { out.writeByte((int)(v & 0x7f) | 0x80); v >>>= 7; }\nout.writeByte((int) v);\n\n// after\n// correct 32-bit varint, max 5 bytes\nWriteBuffer b = ...; b.writeVarint(someInt);","handlingStrategy":"validation","validationCode":"// producer-side encoder check: varint32 of a masked int always fits 5 bytes\nvoid writeVarint32(WriteBuffer b, int v) { b.writeVarint(v); } // use library, never hand-roll","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) { if (e.getMessage().contains(\"32-bit varint\")) dropAndAlertProducer(); else throw e; }","preventionTips":["Never encode negative ints as unsigned 64-bit varints into 32-bit fields.","Reuse WriteBuffer/Proto3Fields writers instead of custom varint code."],"tags":["zipkin","varint","protobuf","malformed"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}