openzipkin/zipkin · error · IllegalArgumentException
traceId is all zeros
Error message
traceId is all zeros
What it means
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.
Source
Thrown at zipkin/src/main/java/zipkin2/Span.java:628
}
}
@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);
}
static String padLeft(String id, int desiredLength) {View on GitHub (pinned to 878ce2a1fa)
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.
Example fix
// before
b.traceId(incomingTraceId); // "0000000000000000"
// after
if (incomingTraceId == null || incomingTraceId.chars().allMatch(c -> c == '0')) {
incomingTraceId = newTraceId();
}
b.traceId(incomingTraceId); Defensive patterns
Strategy: validation
Validate before calling
boolean usable(String t) {
return t != null && !t.isEmpty() && !t.chars().allMatch(c -> c == '0');
}
// traceId = usable(raw) ? raw : newTraceId(); Prevention
- 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.
When it happens
Trigger: Calling normalizeTraceId("0"), normalizeTraceId("0000000000000000"), or a 32-char all-zero ID; passing a trace ID stringified from two 0L longs.
Common situations: 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.
Related errors
- empty trace ID
- traceId == null
- traceId is empty
- should be lower-hex encoded with no prefix
- traceId == 0
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/cac0f8a676a269b6.
Report an issue: GitHub.