openzipkin/zipkin · error · IllegalArgumentException
id is empty
Error message
id is empty
What it means
Span.Builder.id(String id) throws IllegalArgumentException('id is empty') when the argument is non-null but has length 0. An empty string is not a valid lower-hex span ID (valid ones are 1-16 hex chars, padded to 16 internally). The check runs before the length>16 and hex checks.
Source
Thrown at zipkin/src/main/java/zipkin2/Span.java:457
}
return this;
}
/**
* Hex encodes the input as the {@link Span#id()} or throws IllegalArgumentException if the
* input is zero.
*/
public Builder id(long id) {
if (id == 0L) throw new IllegalArgumentException("empty id");
this.id = toLowerHex(id);
return this;
}
/** Sets {@link Span#id()} or throws {@link IllegalArgumentException} if not lower-hex format. */
public Builder id(String id) {
if (id == null) throw new NullPointerException("id == null");
int length = id.length();
if (length == 0) throw new IllegalArgumentException("id is empty");
if (length > 16) throw new IllegalArgumentException("id.length > 16");
if (validateHexAndReturnZeroPrefix(id) == 16) {
throw new IllegalArgumentException("id is all zeros");
}
this.id = length < 16 ? padLeft(id, 16) : id;
return this;
}
/** Sets {@link Span#kind} */
public Builder kind(@Nullable Kind kind) {
this.kind = kind;
return this;
}
/** Sets {@link Span#name} */
public Builder name(@Nullable String name) {
this.name = name == null || name.isEmpty() ? null : name.toLowerCase(Locale.ROOT);
return this;View on GitHub (pinned to 878ce2a1fa)
Solutions
- Validate the extracted ID is non-empty before calling the builder; treat blank as missing.
- Parse the b3 single header with a strict parser instead of String.split so malformed headers fail loudly upstream.
- Fall back to generating a new span ID when the incoming value is blank.
Example fix
// before
b.id(b3Header.split("-")[1]);
// after
String[] parts = b3Header.split("-");
String sid = parts.length > 1 && !parts[1].isEmpty() ? parts[1] : null;
b.id(sid != null ? sid : HexCodec.toLowerHex(ThreadLocalRandom.current().nextLong())); Defensive patterns
Strategy: validation
Validate before calling
boolean validSpanId(String s) {
return s != null && !s.isEmpty() && s.matches("[0-9a-f]{1,16}")
&& s.chars().anyMatch(c -> c != '0');
}
// if (validSpanId(sid)) b.id(sid); else b.id(newIdHex()); Prevention
- Parse b3/traceparent headers with a strict parser, not String.split.
- Validate all incoming ID strings with one shared lower-hex validator.
When it happens
Trigger: Calling .id("") directly, or passing a header value, substring, or trimmed string that ended up as the empty string.
Common situations: Mapping x-b3-spanid or the b3 single header into the builder without normalizing blank values; buggy header parsing (e.g. split("-")[1] on a malformed b3 header) that yields an empty segment.
Related errors
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/366c3c1ee1b24e68.
Report an issue: GitHub.