{"record":{"id":"cac0f8a676a269b6","repo":"openzipkin/zipkin","slug":"traceid-is-all-zeros","errorCode":null,"errorMessage":"traceId is all zeros","messagePattern":"traceId is all zeros","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin/src/main/java/zipkin2/Span.java","lineNumber":628,"sourceCode":"    }\n  }\n\n  @Override public String toString() {\n    return new String(SpanBytesEncoder.JSON_V2.encode(this), UTF_8);\n  }\n\n  /**\n   * Returns a valid lower-hex trace ID, padded left as needed to 16 or 32 characters.\n   *\n   * @throws IllegalArgumentException if oversized or not lower-hex\n   */\n  public static String normalizeTraceId(String traceId) {\n    if (traceId == null) throw new NullPointerException(\"traceId == null\");\n    int length = traceId.length();\n    if (length == 0) throw new IllegalArgumentException(\"traceId is empty\");\n    if (length > 32) throw new IllegalArgumentException(\"traceId.length > 32\");\n    int zeros = validateHexAndReturnZeroPrefix(traceId);\n    if (zeros == length) throw new IllegalArgumentException(\"traceId is all zeros\");\n    if (length == 32 || length == 16) {\n      if (length == 32 && zeros >= 16) return traceId.substring(16);\n      return traceId;\n    } else if (length < 16) {\n      return padLeft(traceId, 16);\n    } else {\n      return padLeft(traceId, 32);\n    }\n  }\n\n  static final String THIRTY_TWO_ZEROS;\n  static {\n    char[] zeros = new char[32];\n    Arrays.fill(zeros, '0');\n    THIRTY_TWO_ZEROS = new String(zeros);\n  }\n\n  static String padLeft(String id, int desiredLength) {","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin/src/main/java/zipkin2/Span.java#L610-L646","documentation":"Span.normalizeTraceId(String) throws IllegalArgumentException('traceId is all zeros') when every character is '0' (validateHexAndReturnZeroPrefix returns the full length). Zipkin requires trace IDs to be non-zero; a zero trace ID cannot identify a trace. The check runs after length/oversize checks and before padding.","triggerScenarios":"Calling normalizeTraceId(\"0\"), normalizeTraceId(\"0000000000000000\"), or a 32-char all-zero ID; passing a trace ID stringified from two 0L longs.","commonSituations":"Receiving all-zero trace IDs from misbehaving clients or from tracestate/traceparent implementations that use zeros as 'invalid'; defaulting trace IDs to \"0\" in config or test data; converting an uninitialized 128-bit ID array to hex.","solutions":["Treat an all-zero trace ID as 'no trace' and start a new trace (generate a fresh ID).","Reject or fix the upstream producer that emits zero trace IDs.","Guard with a regex/long-parse check before normalizing: any parsed value of zero means absent."],"exampleFix":"// before\nb.traceId(incomingTraceId); // \"0000000000000000\"\n\n// after\nif (incomingTraceId == null || incomingTraceId.chars().allMatch(c -> c == '0')) {\n  incomingTraceId = newTraceId();\n}\nb.traceId(incomingTraceId);","handlingStrategy":"validation","validationCode":"boolean usable(String t) {\n  return t != null && !t.isEmpty() && !t.chars().allMatch(c -> c == '0');\n}\n// traceId = usable(raw) ? raw : newTraceId();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat all-zero trace IDs as 'no trace' from broken clients and start a new trace.","Add contract tests for zero/empty/oversized IDs on public ingestion endpoints."],"tags":["zipkin","trace-id","validation"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}