{"record":{"id":"22d992d22d6d34fd","repo":"jaegertracing/jaeger","slug":"cannot-unmarshal-otlp-w","errorCode":null,"errorMessage":"cannot unmarshal OTLP : %w","messagePattern":"cannot unmarshal OTLP : %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/jaeger/internal/extension/jaegerquery/internal/otlp_translator.go","lineNumber":19,"sourceCode":"// Copyright (c) 2024 The Jaeger Authors.\n// SPDX-License-Identifier: Apache-2.0\n\npackage app\n\nimport (\n\t\"fmt\"\n\n\t\"go.opentelemetry.io/collector/pdata/ptrace\"\n\n\t\"github.com/jaegertracing/jaeger-idl/model/v1\"\n\t\"github.com/jaegertracing/jaeger/internal/storage/v2/v1adapter\"\n)\n\nfunc otlp2traces(otlpSpans []byte) ([]*model.Trace, error) {\n\tptraceUnmarshaler := ptrace.JSONUnmarshaler{}\n\totlpTraces, err := ptraceUnmarshaler.UnmarshalTraces(otlpSpans)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot unmarshal OTLP : %w\", err)\n\t}\n\tjaegerBatches := v1adapter.V1BatchesFromTraces(otlpTraces)\n\tvar traces []*model.Trace\n\ttraceMap := make(map[model.TraceID]*model.Trace)\n\tfor _, batch := range jaegerBatches {\n\t\tfor _, span := range batch.Spans {\n\t\t\tif span.Process == nil {\n\t\t\t\tspan.Process = batch.Process\n\t\t\t}\n\t\t\ttrace, ok := traceMap[span.TraceID]\n\t\t\tif !ok {\n\t\t\t\tnewtrace := model.Trace{\n\t\t\t\t\tSpans: []*model.Span{span},\n\t\t\t\t}\n\t\t\t\ttraceMap[span.TraceID] = &newtrace\n\t\t\t\ttraces = append(traces, &newtrace)\n\t\t\t} else {\n\t\t\t\ttrace.Spans = append(trace.Spans, span)","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/cmd/jaeger/internal/extension/jaegerquery/internal/otlp_translator.go#L1-L37","documentation":"otlp2traces decodes raw OTLP JSON bytes into OpenTelemetry ptrace.Traces before converting them to Jaeger model.Trace objects. When ptrace.JSONUnmarshaler.UnmarshalTraces cannot parse the payload (malformed JSON or an OTLP shape it does not accept), the error is wrapped as \"cannot unmarshal OTLP : %w\" so the underlying decoder reason is preserved. Called via transformOTLP, this is the entry point for OTLP-format input to the query extension.","triggerScenarios":"transformOTLP -> otlp2traces is invoked with a []byte payload that fails ptrace.JSONUnmarshaler.UnmarshalTraces: syntactically invalid JSON, JSON that is not an OTLP ExportTraceServiceRequest-compatible structure, missing required fields such as resourceSpans, or wrong field types.","commonSituations":"A client posts a Jaeger JSON payload (or arbitrary JSON) to an endpoint that expects OTLP JSON; a span field has the wrong type (e.g. traceId as integer instead of hex string); empty or truncated request bodies; version drift where the payload uses an OTLP field name the embedded OTel collector version does not recognize.","solutions":["Inspect the wrapped inner error (%w) to identify the exact JSON/OTLP decode failure and fix the payload accordingly.","Validate the payload is real OTLP JSON (ExportTraceServiceRequest shape, hex-encoded traceId/spanId, proper resourceSpans/scopeSpans nesting) before sending.","If sending Jaeger-format JSON, send it to the Jaeger-native endpoint instead of the OTLP one.","Check that client and server OTLP schema versions are compatible; regenerate payloads from a current SDK/exporter."],"exampleFix":"// before: sending Jaeger-style JSON to the OTLP translator\nPOST body: {\"data\":[{\"traceID\":\"abc\",\"spans\":[...]}]}\n\n// after: correct OTLP JSON shape\n{\"resourceSpans\":[{\"resource\":{\"attributes\":[...]},\"scopeSpans\":[{\"spans\":[{\"traceId\":\"0af7651916cd43dd8448eb211c80319c\",\"spanId\":\"b7ad6b7169203331\",\"name\":\"op\",\"kind\":\"SPAN_KIND_SERVER\"}]}]}]}","handlingStrategy":"validation","validationCode":"var buf map[string]any\nif err := json.Unmarshal(otlpSpans, &buf); err != nil {\n    return fmt.Errorf(\"payload is not valid JSON: %w\", err)\n}\nif _, ok := buf[\"resourceSpans\"]; !ok {\n    return errors.New(\"payload lacks resourceSpans; not an OTLP ExportTraceServiceRequest\")\n}","typeGuard":"func isOTLPJSON(body []byte) bool {\n    var m map[string]json.RawMessage\n    return json.Unmarshal(body, &m) == nil && m[\"resourceSpans\"] != nil\n}","tryCatchPattern":"traces, err := otlp2traces(otlpSpans)\nif err != nil {\n    var syntaxErr *json.SyntaxError\n    if errors.As(err, &syntaxErr) {\n        return fmt.Errorf(\"malformed OTLP JSON at offset %d: %w\", syntaxErr.Offset, err)\n    }\n    return fmt.Errorf(\"OTLP decode rejected: %w\", err)\n}","preventionTips":["Send payloads only from an OTel SDK/OTLP exporter in JSON mode; never hand-craft OTLP JSON.","Validate with isOTLPJSON or a schema check before posting to OTLP endpoints.","Log the first ~200 bytes of a failing body to catch truncation or wrong-format posts early."],"tags":["otlp","unmarshal","json","tracing"],"backgroundTag":"otlp-json-unmarshal-failed","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}