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
- 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.
- Ensure the client completes the HTTP request without aborting the body stream (check timeouts/proxy buffering limits).
- Validate enums and field types client-side against the opentelemetry-proto schema before export.
- 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
- Generate requests via protobuf-generated classes only
- Keep HTTP clients/proxies from truncating or re-encoding bodies
- Match field types exactly to proto3 JSON mapping (strings for int64, base64 for bytes)
- Pin client and collector to compatible opentelemetry-proto versions
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
- OtlpTraceParseException (syntax error, message built from sy
- OTLP/HTTP decompressed request body exceeded max size: limit
- OTLP/HTTP request body exceeded max size: limit=${limit}
- Resource attribute `service.name` is required to save OTLP m
- Resource attribute `pinpoint.agentId` is required to save OT
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/2f4f7c9ecaa3609d.
Report an issue: GitHub.