{"record":{"id":"01310251f5301946","repo":"pinpoint-apm/pinpoint","slug":"invalid-traceid-error","errorCode":null,"errorMessage":"invalid traceId: ${error}","messagePattern":"invalid traceId: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/mapper/OtlpIdValidator.java","lineNumber":71,"sourceCode":"        return spanIdError(spanId) == null;\n    }\n\n    /**\n     * A parent span reference is valid when it is either absent (a root span) or itself a valid span ID.\n     * A present-but-malformed parent is treated as invalid so the owning span can be rejected.\n     */\n    public static boolean isValidParentSpanId(ByteString parentSpanId) {\n        return ByteStringUtils.isEmpty(parentSpanId) || isValidSpanId(parentSpanId);\n    }\n\n    /**\n     * @return the 16-byte trace ID\n     * @throws IllegalArgumentException if empty, not 16 bytes, or all-zero\n     */\n    public static byte[] validateTraceId(ByteString traceId) {\n        final String error = traceIdError(traceId);\n        if (error != null) {\n            throw new IllegalArgumentException(\"invalid traceId: \" + error);\n        }\n        return traceId.toByteArray();\n    }\n\n    /**\n     * @return the span ID as a big-endian long\n     * @throws IllegalArgumentException if empty, not 8 bytes, or all-zero\n     */\n    public static long validateSpanId(ByteString spanId) {\n        final String error = spanIdError(spanId);\n        if (error != null) {\n            throw new IllegalArgumentException(\"invalid spanId: \" + error);\n        }\n        return ByteStringUtils.parseLong(spanId);\n    }\n\n    private static String traceIdError(ByteString traceId) {\n        return idError(traceId, TRACE_ID_LEN);","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/mapper/OtlpIdValidator.java#L53-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the emitting SDK produces 16 random bytes for traceId per W3C Trace Context (use the official OpenTelemetry SDK, not hand-rolled IDs).","Drop or fix spans carrying all-zero traceIds before export — they are invalid by spec and should not be sent.","When bridging from 64-bit legacy IDs, zero-pad to 16 bytes and confirm not all zero.","Wrap parse/export code in try-catch for IllegalArgumentException and log-and-drop the offending span instead of failing the whole batch."],"exampleFix":"// before\nbyte[] traceId = new byte[8]; // wrong length\n// after\nbyte[] traceId = new byte[16];\nThreadLocalRandom.current().nextBytes(traceId); // 16 random bytes, not all zero","handlingStrategy":"validation","validationCode":"boolean validTraceId(byte[] id) {\n    return id != null && id.length == 16 && !Arrays.equals(id, new byte[16]);\n}","typeGuard":"static boolean isUsableTraceId(ByteString traceId) {\n    return traceId != null\n        && traceId.size() == 16\n        && !traceId.equals(ByteString.copyFrom(new byte[16]));\n}","tryCatchPattern":"try {\n    byte[] traceId = OtlpIdValidator.validateTraceId(span.getTraceId());\n} catch (IllegalArgumentException e) {\n    log.warn(\"dropping span: {}\", e.getMessage());\n    return; // skip invalid span, keep processing the batch\n}","preventionTips":["Use the official OpenTelemetry SDK to generate 16-byte trace IDs","Never export spans with all-zero or empty trace IDs","Zero-pad legacy 64-bit IDs to 16 bytes when bridging formats","Add batch pre-validation that drops invalid IDs before export"],"tags":["java","otlp","trace-id","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}