pinpoint-apm/pinpoint · error · IllegalArgumentException
invalid spanId: ${error}
Error message
invalid spanId: ${error} What it means
OtlpIdValidator.validateSpanId validates an OTLP spanId ByteString: it must be non-empty, exactly 8 bytes, and not all zeros; on failure it throws IllegalArgumentException with the specific reason. Valid span IDs are required since they become the span's storage key.
Source
Thrown at otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/mapper/OtlpIdValidator.java:83
* @return the 16-byte trace ID
* @throws IllegalArgumentException if empty, not 16 bytes, or all-zero
*/
public static byte[] validateTraceId(ByteString traceId) {
final String error = traceIdError(traceId);
if (error != null) {
throw new IllegalArgumentException("invalid traceId: " + error);
}
return traceId.toByteArray();
}
/**
* @return the span ID as a big-endian long
* @throws IllegalArgumentException if empty, not 8 bytes, or all-zero
*/
public static long validateSpanId(ByteString spanId) {
final String error = spanIdError(spanId);
if (error != null) {
throw new IllegalArgumentException("invalid spanId: " + error);
}
return ByteStringUtils.parseLong(spanId);
}
private static String traceIdError(ByteString traceId) {
return idError(traceId, TRACE_ID_LEN);
}
private static String spanIdError(ByteString spanId) {
return idError(spanId, SPAN_ID_LEN);
}
private static String idError(ByteString id, int expectedLen) {
if (ByteStringUtils.isEmpty(id)) {
return "empty";
}
if (id.size() != expectedLen) {
return "length " + id.size() + " (expected " + expectedLen + ")";View on GitHub (pinned to 744c3d3075)
Solutions
- Generate 8 random bytes for every exported span's spanId using the official OpenTelemetry SDK.
- Never export spans with empty or all-zero spanIds — filter them out before calling the collector.
- When bridging IDs, pad/truncate to exactly 8 bytes and verify they are not all zero.
- Catch IllegalArgumentException around span mapping and skip/log the invalid span rather than rejecting the batch.
Example fix
// before Span.newBuilder().setSpanId(ByteString.EMPTY)... // empty id -> throws // after byte[] spanId = new byte[8]; ThreadLocalRandom.current().nextBytes(spanId); Span.newBuilder().setSpanId(ByteString.copyFrom(spanId))...
Defensive patterns
Strategy: validation
Validate before calling
boolean validSpanId(byte[] id) {
return id != null && id.length == 8 && !Arrays.equals(id, new byte[8]);
} Type guard
static boolean isUsableSpanId(ByteString spanId) {
return spanId != null
&& spanId.size() == 8
&& !spanId.equals(ByteString.copyFrom(new byte[8]));
} Try / catch
try {
long spanId = OtlpIdValidator.validateSpanId(span.getSpanId());
} catch (IllegalArgumentException e) {
log.warn("skipping span with bad spanId: {}", e.getMessage());
continue; // skip span, continue batch
} Prevention
- Generate 8-byte random span IDs via the official SDK
- Filter out empty/all-zero span IDs before export
- Validate hex-string IDs are 16 hex chars before converting to bytes
- Drop unsampled/placeholder spans instead of exporting them with sentinel IDs
When it happens
Trigger: Exporting spans with an empty spanId, a spanId that is not 8 bytes long, or all-zero bytes (OTLP's invalid-id sentinel), typically from hand-constructed Span messages or bridged telemetry.
Common situations: Test fixtures using ByteString.EMPTY; bridges from systems with different span-id widths; code that sets spanId from a parsed hex string shorter than 16 hex chars; SDKs producing zeroed IDs for unsampled spans that were exported anyway.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Resource attribute `service.name` is required to save OTLP m
- Resource attribute `pinpoint.agentId` is required to save OT
- invalid traceId: ${error}
- invalid pinpoint.agentName=${agentName}
- annotationKey name must not be empty
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/5af1b62af69a718c.
Report an issue: GitHub.