pinpoint-apm/pinpoint · error · OtlpTraceParseException

OtlpTraceParseException (message from e.getMessage())

Error message

OtlpTraceParseException (message from e.getMessage())

What it means

Same parse() path as the JSON syntax error, but this throw wraps IOException | IllegalArgumentException from the protobuf JSON merge. The message is the underlying e.getMessage(); the javadoc notes Jackson appends the full JsonLocation (source content) to JsonProcessingException messages, so the server deliberately redacts the source. Any I/O problem reading the body or illegal argument during proto JSON parsing surfaces here as OtlpTraceParseException.

Source

Thrown at otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/controller/OtlpJsonTraceParser.java:77

            "spanId", "span_id",
            "parentSpanId", "parent_span_id");

    private static final JsonFactory JSON_FACTORY = new JsonFactory();
    private static final JsonFormat.Parser PROTO_JSON_PARSER = JsonFormat.parser().ignoringUnknownFields();

    private OtlpJsonTraceParser() {
    }

    public static ExportTraceServiceRequest parse(byte[] body) {
        try {
            final String protoJson = rewriteIdsToBase64(body);
            final ExportTraceServiceRequest.Builder builder = ExportTraceServiceRequest.newBuilder();
            PROTO_JSON_PARSER.merge(protoJson, builder);
            return builder.build();
        } catch (JsonProcessingException e) {
            throw new OtlpTraceParseException(syntaxErrorMessage(e), e);
        } catch (IOException | IllegalArgumentException e) {
            throw new OtlpTraceParseException(e.getMessage(), e);
        }
    }

    /**
     * Jackson's {@link JsonProcessingException#getMessage()} appends the full {@code JsonLocation}
     * ({@code [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1,
     * column: 19]}), sometimes twice, which more than doubles the message without adding anything a
     * client can act on. Keep the cause and the position only — in the shape the OTel collector's
     * own JSON errors take.
     */
    static String syntaxErrorMessage(JsonProcessingException e) {
        // The original message can embed a location too ("(for Array starting at [Source: ...])").
        final String original = SOURCE_LOCATION.matcher(e.getOriginalMessage()).replaceAll("line $1, column $2");
        final JsonLocation location = e.getLocation();
        if (location == null) {
            return original;
        }
        return original + " (line " + location.getLineNr() + ", column " + location.getColumnNr() + ")";

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Fix the OTLP JSON content per the embedded message — most commonly an invalid enum name or wrongly typed field; regenerate with the official protobuf JSON printer.
  2. Ensure the client completes the HTTP request without aborting the body stream (check timeouts/proxy buffering limits).
  3. Validate enums and field types client-side against the opentelemetry-proto schema before export.
  4. If ids/bytes fields are the problem, base64-encode them as required by proto3 JSON mapping.

Example fix

// before
span.setKind("SPAN_KIND_INTERNAL_X"); // invalid enum -> IllegalArgumentException in merge
// after
span.setKind(Span.SpanKind.SPAN_KIND_INTERNAL);
Defensive patterns

Strategy: try-catch

Validate before calling

// client-side pre-check of proto-JSON rules
EnumVerifier.getDescriptor().verify(value) // or verify enum names/types against opentelemetry-proto descriptors before export

Type guard

static boolean hasValidEnumNames(ExportTraceServiceRequest req) {
    return req.getResourceSpansList().stream()
        .allMatch(rs -> rs.getScopeSpansList().stream()
            .allMatch(ss -> ss.getSpansList().stream()
                .allMatch(s -> Span.SpanKind.forNumber(s.getKindValue()) != null)));
}

Try / catch

try {
    ExportTraceServiceRequest req = parse(body);
} catch (OtlpTraceParseException e) {
    if (e.getCause() instanceof IOException) { retryLater(); }          // transport issue
    else { log.error("invalid OTLP proto JSON: {}", e.getMessage()); }   // content issue
}

Prevention

When it happens

Trigger: Request body stream fails mid-read (IOException), or the merged JSON is structurally parseable but violates proto JSON rules (IllegalArgumentException): e.g. invalid enum string, wrong wire representation of bytes/int64, or a null where a message is required.

Common situations: Client sends a partially valid OTLP JSON document (e.g. invalid enum value like a non-existent SpanKind); interrupted connections; bodies exceeding internal limits cut mid-stream; sending numbers as strings where proto JSON disallows it.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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