pinpoint-apm/pinpoint · error · IllegalArgumentException

invalid traceId

Error message

invalid traceId: ${error}

What it means

OtlpIdValidator.validateTraceId checks an incoming OTLP traceId ByteString for emptiness, correct 16-byte length, and non-all-zero content (the W3C/OTLP invalid-trace-id rule). Any violation throws IllegalArgumentException with the specific reason. Valid trace IDs are required to key spans into pinpoint's trace storage.

Solutions

  1. Ensure the emitting SDK produces 16 random bytes for traceId per W3C Trace Context (use the official OpenTelemetry SDK, not hand-rolled IDs).
  2. Drop or fix spans carrying all-zero traceIds before export — they are invalid by spec and should not be sent.
  3. When bridging from 64-bit legacy IDs, zero-pad to 16 bytes and confirm not all zero.
  4. Wrap parse/export code in try-catch for IllegalArgumentException and log-and-drop the offending span instead of failing the whole batch.

Example fix

// before
byte[] traceId = new byte[8]; // wrong length
// after
byte[] traceId = new byte[16];
ThreadLocalRandom.current().nextBytes(traceId); // 16 random bytes, not all zero
Defensive patterns

Strategy: validation

Validate before calling

boolean validTraceId(byte[] id) {
    return id != null && id.length == 16 && !Arrays.equals(id, new byte[16]);
}

Type guard

static boolean isUsableTraceId(ByteString traceId) {
    return traceId != null
        && traceId.size() == 16
        && !traceId.equals(ByteString.copyFrom(new byte[16]));
}

Try / catch

try {
    byte[] traceId = OtlpIdValidator.validateTraceId(span.getTraceId());
} catch (IllegalArgumentException e) {
    log.warn("dropping span: {}", e.getMessage());
    return; // skip invalid span, keep processing the batch
}

Prevention

When it happens

Trigger: Exporting spans whose parent SDK generated a traceId that is empty, not exactly 16 bytes, or all zero bytes (0x00 * 16, the OTLP 'invalid id' sentinel) — e.g. spans created outside a sampled context.

Common situations: Custom/naive tracers generating 8-byte or 32-byte trace IDs; manually constructed spans in tests or bridges using empty ByteString as a placeholder; converting from another tracing format (e.g. 64-bit legacy IDs) without padding to 16 bytes.

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


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/01310251f5301946. Report an issue: GitHub.

Appendix: source

Thrown at otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/mapper/OtlpIdValidator.java:71

        return spanIdError(spanId) == null;
    }

    /**
     * A parent span reference is valid when it is either absent (a root span) or itself a valid span ID.
     * A present-but-malformed parent is treated as invalid so the owning span can be rejected.
     */
    public static boolean isValidParentSpanId(ByteString parentSpanId) {
        return ByteStringUtils.isEmpty(parentSpanId) || isValidSpanId(parentSpanId);
    }

    /**
     * @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);

View on GitHub (pinned to 744c3d3075)