{"record":{"id":"5c6f9fd1c2169e2d","repo":"openzipkin/zipkin","slug":"traceid-is-empty","errorCode":null,"errorMessage":"traceId is empty","messagePattern":"traceId is empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin/src/main/java/zipkin2/Span.java","lineNumber":625,"sourceCode":"    }\n\n    Builder() {\n    }\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);","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin/src/main/java/zipkin2/Span.java#L607-L643","documentation":"Span.normalizeTraceId(String) throws IllegalArgumentException('traceId is empty') when the argument is non-null but zero-length. An empty string carries no ID bits, so there is nothing to pad or normalize. This is distinct from null (NPE, error 128) and from all-zeros (error 130).","triggerScenarios":"Calling normalizeTraceId(\"\") or Span.Builder.traceId(\"\"), typically with a header/MDC value that was present but blank.","commonSituations":"Log-correlation code reading an empty traceId MDC entry (logger layout wrote an empty field); B3 header extraction where the upstream service sent x-b3-traceid: with no value; string manipulation (trim/substring) that produced \"\".","solutions":["Treat blank as absent: if (t == null || t.isEmpty()) skip / generate new trace ID.","Fix the upstream header sender that emits empty trace-ID headers.","Use isBlank-style checks when reading MDC/log fields populated by other frameworks."],"exampleFix":"// before\nb.traceId(mdc.get(\"traceId\"));\n\n// after\nString t = mdc.get(\"traceId\");\nb.traceId(t == null || t.isEmpty() ? newTraceId() : t);","handlingStrategy":"validation","validationCode":"if (raw != null && !raw.isEmpty()) traceId = Span.normalizeTraceId(raw);\nelse traceId = newTraceId();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use isBlank checks on MDC/log-correlation fields.","Fix upstream emitters that send empty trace-ID headers."],"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"}