{"record":{"id":"9c6e480ccda76710","repo":"jaegertracing/jaeger","slug":"invalid-length-d-of-decoded-trace-id-q-expected","errorCode":null,"errorMessage":"invalid length %d of decoded trace ID %q, expected %d bytes","messagePattern":"invalid length (.+?) of decoded trace ID %q, expected (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/clickhouse/tracestore/dbmodel/from.go","lineNumber":78,"sourceCode":"\tputAttributes(\n\t\tscope.Attributes(),\n\t\t&sr.ScopeAttributes,\n\t\tspanForWarnings,\n\t)\n\n\treturn scope\n}\n\n// decodeTraceID decodes a hex string into a pcommon.TraceID, validating that\n// it contains exactly 16 bytes so the conversion cannot panic on corrupted rows.\nfunc decodeTraceID(s string) (pcommon.TraceID, error) {\n\tvar id pcommon.TraceID\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 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","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/clickhouse/tracestore/dbmodel/from.go#L60-L96","documentation":"decodeTraceID converts a hex string from ClickHouse into a 16-byte pcommon.TraceID. This error is thrown when the hex string decodes successfully but does not yield exactly 16 bytes, which is the fixed size of an OpenTelemetry trace ID. The library validates this to guarantee a well-formed pcommon.TraceID can be constructed.","triggerScenarios":"Calling FromRow/convertSpan with a SpanRow whose TraceID column holds a hex string that decodes to fewer or more than 16 bytes, e.g. an empty string, a 32-hex-digit ID from a 16-byte-encoded source that was truncated, or a legacy 8-byte trace ID (16 hex chars).","commonSituations":"Migrating data from older Jaeger storage where trace IDs were 8 bytes; manual data inserts with malformed IDs; ClickHouse columns typed as String allowing arbitrary-length values.","solutions":["Verify the trace IDs stored in ClickHouse are 32 hex characters (16 bytes) once decoded","Check the ingestion pipeline — the writer must zero-pad or preserve full 16-byte trace IDs","Inspect the offending row(s) and repair or drop malformed trace_id values","If legacy 8-byte IDs exist, migrate them by left-padding with zeros to 16 bytes before storing"],"exampleFix":"// before: legacy 8-byte trace id string \"abcdef0123456789\" (8 bytes) fails validation\n// after: pad to 16 bytes before writing/decoding\npadded := strings.Repeat(\"0\", 32-len(s)) + s\nid, err := decodeTraceID(padded)","handlingStrategy":"validation","validationCode":"func validTraceIDHex(s string) bool {\n    b, err := hex.DecodeString(s)\n    return err == nil && len(b) == 16\n}\n// before querying: if !validTraceIDHex(row.TraceID) { skip/repair }","typeGuard":"func isTraceID(s string) (pcommon.TraceID, bool) {\n    var id pcommon.TraceID\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)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid length\") {\n        log.Warn(\"skipping row with malformed trace ID\", \"err\", err)\n        continue\n    }\n    return err\n}","preventionTips":["Always write full 16-byte (32 hex char) trace IDs to ClickHouse","Zero-pad legacy 8-byte IDs during migration","Validate ID formats at ingestion, not at read time"],"tags":["clickhouse","trace-id","data-corruption","hex-decoding"],"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"}