{"record":{"id":"bf00e5ed57f3d00d","repo":"jaegertracing/jaeger","slug":"invalid-length-d-of-decoded-span-id-q-expected","errorCode":null,"errorMessage":"invalid length %d of decoded span ID %q, expected %d bytes","messagePattern":"invalid length (.+?) of decoded span ID %q, expected (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/clickhouse/tracestore/dbmodel/from.go","lineNumber":93,"sourceCode":"\t\treturn id, err\n\t}\n\tif len(b) != len(id) {\n\t\treturn id, fmt.Errorf(\"invalid length %d of decoded trace ID %q, expected %d bytes\", len(b), s, len(id))\n\t}\n\tcopy(id[:], b)\n\treturn id, nil\n}\n\n// decodeSpanID decodes a hex string into a pcommon.SpanID, validating that\n// it contains exactly 8 bytes so the conversion cannot panic on corrupted rows.\nfunc 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)","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/clickhouse/tracestore/dbmodel/from.go#L75-L111","documentation":"decodeSpanID converts a hex string into a fixed 8-byte pcommon.SpanID. This error is thrown when the hex string decodes but the resulting byte slice is not exactly 8 bytes. The strict length check ensures a valid pcommon.SpanID can always be populated.","triggerScenarios":"Calling FromRow/convertSpan with a SpanRow whose ID or ParentSpanID column decodes to a byte length other than 8, e.g. an empty span ID, a 16-hex-char (8-byte) value stored truncated/padded differently, or oversized strings.","commonSituations":"Data written by another tooling version with different span-ID widths; manual SQL edits; corrupted rows from a bad ETL job.","solutions":["Confirm span IDs stored in ClickHouse are exactly 16 hex characters (8 bytes)","Check the writer path that serializes span IDs to ensure it emits full-length hex","Fix or drop the malformed rows","Add a validation step at ingestion to reject non-8-byte span IDs before they reach storage"],"exampleFix":"// before: 12-hex-char span id fails\n// after: validate before persisting\nif len(spanIDHex) != 16 { return fmt.Errorf(\"span ID must be 16 hex chars, got %d\", len(spanIDHex)) }","handlingStrategy":"validation","validationCode":"func validSpanIDHex(s string) bool {\n    b, err := hex.DecodeString(s)\n    return err == nil && len(b) == 8\n}\n// before FromRow: if !validSpanIDHex(row.ID) { handle }","typeGuard":"func isSpanID(s string) (pcommon.SpanID, bool) {\n    var id pcommon.SpanID\n    b, err := hex.DecodeString(s)\n    if err != nil || len(b) != len(id) { return id, false }\n    copy(id[:], b)\n    return id, true\n}","tryCatchPattern":"span, err := FromRow(row)\nvar decodeErr *fmt.wrapError\nif errors.As(err, &decodeErr) && strings.Contains(err.Error(), \"span ID\") {\n    log.Warn(\"malformed span ID, skipping row\", \"err\", err)\n} else if err != nil {\n    return err\n}","preventionTips":["Enforce 16-hex-char span IDs in all writers","Reject empty or placeholder span IDs at ingestion","Add a schema/data quality check that scans for malformed IDs"],"tags":["clickhouse","span-id","hex-decoding","data-validation"],"backgroundTag":"invalid-span-id-length","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}