{"record":{"id":"ef601e3b7ede9a17","repo":"jaegertracing/jaeger","slug":"failed-to-decode-trace-id-w","errorCode":null,"errorMessage":"failed to decode trace ID: %w","messagePattern":"failed to decode trace ID: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/clickhouse/tracestore/dbmodel/from.go","lineNumber":104,"sourceCode":"func decodeSpanID(s string) (pcommon.SpanID, error) {\n\tvar id pcommon.SpanID\n\tb, err := hex.DecodeString(s)\n\tif err != nil {\n\t\treturn id, err\n\t}\n\tif len(b) != len(id) {\n\t\treturn id, fmt.Errorf(\"invalid length %d of decoded span ID %q, expected %d bytes\", len(b), s, len(id))\n\t}\n\tcopy(id[:], b)\n\treturn id, nil\n}\n\nfunc convertSpan(sr *SpanRow) (ptrace.Span, error) {\n\tspan := ptrace.NewSpan()\n\tspan.SetStartTimestamp(pcommon.NewTimestampFromTime(sr.StartTime))\n\ttraceId, err := decodeTraceID(sr.TraceID)\n\tif err != nil {\n\t\treturn span, fmt.Errorf(\"failed to decode trace ID: %w\", err)\n\t}\n\tspan.SetTraceID(traceId)\n\tspanId, err := decodeSpanID(sr.ID)\n\tif err != nil {\n\t\treturn span, fmt.Errorf(\"failed to decode span ID: %w\", err)\n\t}\n\tspan.SetSpanID(spanId)\n\tif sr.ParentSpanID != \"\" {\n\t\tparentSpanId, err := decodeSpanID(sr.ParentSpanID)\n\t\tif err != nil {\n\t\t\treturn span, fmt.Errorf(\"failed to decode parent span ID: %w\", err)\n\t\t}\n\t\tspan.SetParentSpanID(parentSpanId)\n\t}\n\tspan.TraceState().FromRaw(sr.TraceState)\n\tspan.SetName(sr.Name)\n\tspan.SetKind(jptrace.StringToSpanKind(sr.Kind))\n\tspan.SetEndTimestamp(pcommon.NewTimestampFromTime(sr.StartTime.Add(time.Duration(sr.Duration))))","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/clickhouse/tracestore/dbmodel/from.go#L86-L122","documentation":"convertSpan wraps any failure from decodeTraceID (invalid hex characters or wrong decoded length) with this contextual message. It indicates the stored trace ID for the row could not be converted into a pcommon.TraceID, so the span cannot be returned.","triggerScenarios":"FromRow is called on a SpanRow whose TraceID string is not valid hex (odd length, non-hex characters) or decodes to a length other than 16 bytes.","commonSituations":"Reading rows written by external producers; corrupted ClickHouse data; schema drift where trace_id changed representation between storage versions.","solutions":["Inspect the raw trace_id value in ClickHouse for the failing row","Fix invalid hex at the data level or in the ingestion pipeline","Ensure the writer uses the same hex encoding (lowercase, full 32 chars) as the reader expects","Add ingest-time validation of trace ID format"],"exampleFix":"// before\ntraceId, err := decodeTraceID(sr.TraceID)\n// after: guard caller-side\nif len(sr.TraceID) != 32 { return span, fmt.Errorf(\"trace ID %q is not 32 hex chars\", sr.TraceID) }\ntraceId, err := decodeTraceID(sr.TraceID)","handlingStrategy":"try-catch","validationCode":"if len(sr.TraceID) != 32 {\n    return fmt.Errorf(\"trace ID %q must be 32 hex chars before conversion\", sr.TraceID)\n}","typeGuard":"func hasValidTraceID(sr *SpanRow) bool {\n    _, ok := isTraceID(sr.TraceID)\n    return ok\n}","tryCatchPattern":"span, err := FromRow(sr)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to decode trace ID\") {\n        metrics.MalformedTraceID.Inc(1)\n        continue // skip poisoned row\n    }\n    return err\n}","preventionTips":["Validate trace IDs at write time","Use a single shared encoder for trace IDs across services","Monitor decode-error metrics to catch producer regressions early"],"tags":["clickhouse","trace-id","error-wrapping","data-corruption"],"backgroundTag":"invalid-trace-id-length","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}