{"record":{"id":"b33758aef69b7a94","repo":"openzipkin/zipkin","slug":"hex-field-greater-than-32-chars-long","errorCode":null,"errorMessage":"hex field greater than 32 chars long: {}","messagePattern":"hex field greater than 32 chars long: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin/src/main/java/zipkin2/internal/ReadBuffer.java","lineNumber":308,"sourceCode":"\n  abstract int pos();\n\n  abstract short readShort();\n\n  abstract int readInt();\n\n  abstract long readLong();\n\n  abstract long readLongLe();\n\n  @Override public final int read() {\n    return available() > 0 ? readByteUnsafe() : -1;\n  }\n\n  final String readBytesAsHex(int length) {\n    // All our hex fields are at most 32 characters.\n    if (length > 32) {\n      throw new IllegalArgumentException(\"hex field greater than 32 chars long: \" + length);\n    }\n\n    require(length);\n    char[] result = RecyclableBuffers.shortStringBuffer();\n    int hexLength = length * 2;\n    for (int i = 0; i < hexLength; i += 2) {\n      byte b = readByteUnsafe();\n      result[i + 0] = HEX_DIGITS[(b >> 4) & 0xf];\n      result[i + 1] = HEX_DIGITS[b & 0xf];\n    }\n    return new String(result, 0, hexLength);\n  }\n\n  /**\n   * @return the value read. Use {@link WriteBuffer#varintSizeInBytes(long)} to tell how many bytes.\n   * @throws IllegalArgumentException if more than 64 bits were encoded\n   */\n  // included in the main api as this is used commonly, for example reading proto tags","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin/src/main/java/zipkin2/internal/ReadBuffer.java#L290-L326","documentation":"Zipkin IDs (trace/span/parent) are at most 16 bytes, i.e. 32 hex characters. ReadBuffer.readBytesAsHex converts fixed-length byte fields to hex and throws 'hex field greater than 32 chars long: N' when a length-delimited ID field in the payload is longer than 16 bytes — the decoder refuses impossible IDs rather than truncating.","triggerScenarios":"PROTO3 (or thrift) decoding where a trace_id/span_id field carries more than 16 bytes — e.g. a 32-byte ID mistakenly sent as raw bytes instead of the 16-byte binary form, or a misread length prefix on an ID field.","commonSituations":"Producers that treat the 32-char hex string as bytes (32 bytes instead of 16); systems generating non-Zipkin 128-bit-plus identifiers; payload corruption shifting a length prefix.","solutions":["On the producer, convert hex IDs to their 16-byte binary form before putting them into proto3/thrift fields (Zipkin never transports ID hex in binary fields).","Verify the length-delimited prefix of the ID field is exactly 16 (0x10) for a 128-bit ID or 8 for 64-bit.","Check the bytes are proto3 and not hex-encoded JSON IDs pasted into a binary field.","Drop the malformed span and log the offending ID bytes for the producer team."],"exampleFix":"// before\n// sent the 32-char hex string as bytes (32 bytes)\nfield.write(b, span.traceId().getBytes(UTF_8));\n\n// after\n// send the 16-byte binary form; hex conversion happens on read\nbyte[] id = BufferUtil.lowerHexToUnsignedBytes(span.traceId());\nfield.write(b, id);","handlingStrategy":"validation","validationCode":"// producer-side: verify ID hex length before binary conversion\nbyte[] toIdBytes(String hex) {\n  if (hex.length() != 16 && hex.length() != 32) throw new IllegalArgumentException(\"bad id: \" + hex);\n  return zipkin2.internal.BufferUtil.lowerHexToUnsignedBytes(hex);\n}","typeGuard":"boolean isValidTraceIdHex(String s) { return s != null && s.matches(\"[0-9a-f]{16}([0-9a-f]{16})?\"); }","tryCatchPattern":null,"preventionTips":["Transport IDs as 8 or 16 binary bytes, never as hex text inside binary fields.","Reject IDs that are not exactly 16 or 32 lowercase hex chars at ingest."],"tags":["zipkin","protobuf","trace-id","malformed"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}