openzipkin/zipkin · error · IllegalArgumentException

traceId is empty

Error message

traceId is empty

What it means

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).

Source

Thrown at zipkin/src/main/java/zipkin2/Span.java:625

    }

    Builder() {
    }
  }

  @Override public String toString() {
    return new String(SpanBytesEncoder.JSON_V2.encode(this), UTF_8);
  }

  /**
   * Returns a valid lower-hex trace ID, padded left as needed to 16 or 32 characters.
   *
   * @throws IllegalArgumentException if oversized or not lower-hex
   */
  public static String normalizeTraceId(String traceId) {
    if (traceId == null) throw new NullPointerException("traceId == null");
    int length = traceId.length();
    if (length == 0) throw new IllegalArgumentException("traceId is empty");
    if (length > 32) throw new IllegalArgumentException("traceId.length > 32");
    int zeros = validateHexAndReturnZeroPrefix(traceId);
    if (zeros == length) throw new IllegalArgumentException("traceId is all zeros");
    if (length == 32 || length == 16) {
      if (length == 32 && zeros >= 16) return traceId.substring(16);
      return traceId;
    } else if (length < 16) {
      return padLeft(traceId, 16);
    } else {
      return padLeft(traceId, 32);
    }
  }

  static final String THIRTY_TWO_ZEROS;
  static {
    char[] zeros = new char[32];
    Arrays.fill(zeros, '0');
    THIRTY_TWO_ZEROS = new String(zeros);

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Treat blank as absent: if (t == null || t.isEmpty()) skip / generate new trace ID.
  2. Fix the upstream header sender that emits empty trace-ID headers.
  3. Use isBlank-style checks when reading MDC/log fields populated by other frameworks.

Example fix

// before
b.traceId(mdc.get("traceId"));

// after
String t = mdc.get("traceId");
b.traceId(t == null || t.isEmpty() ? newTraceId() : t);
Defensive patterns

Strategy: validation

Validate before calling

if (raw != null && !raw.isEmpty()) traceId = Span.normalizeTraceId(raw);
else traceId = newTraceId();

Prevention

When it happens

Trigger: Calling normalizeTraceId("") or Span.Builder.traceId(""), typically with a header/MDC value that was present but blank.

Common situations: 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 "".

Related errors


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