jaegertracing/jaeger · error
failed to decode span ID: %w
Error message
failed to decode span ID: %w
What it means
convertSpan wraps failures from decodeSpanID for the span's own ID with this message. The stored span ID is not valid hex or does not decode to exactly 8 bytes, so the pcommon.Span cannot be built.
Source
Thrown at internal/storage/v2/clickhouse/tracestore/dbmodel/from.go:109
}
if len(b) != len(id) {
return id, fmt.Errorf("invalid length %d of decoded span ID %q, expected %d bytes", len(b), s, len(id))
}
copy(id[:], b)
return id, nil
}
func convertSpan(sr *SpanRow) (ptrace.Span, error) {
span := ptrace.NewSpan()
span.SetStartTimestamp(pcommon.NewTimestampFromTime(sr.StartTime))
traceId, err := decodeTraceID(sr.TraceID)
if err != nil {
return span, fmt.Errorf("failed to decode trace ID: %w", err)
}
span.SetTraceID(traceId)
spanId, err := decodeSpanID(sr.ID)
if err != nil {
return span, fmt.Errorf("failed to decode span ID: %w", err)
}
span.SetSpanID(spanId)
if sr.ParentSpanID != "" {
parentSpanId, err := decodeSpanID(sr.ParentSpanID)
if err != nil {
return span, fmt.Errorf("failed to decode parent span ID: %w", err)
}
span.SetParentSpanID(parentSpanId)
}
span.TraceState().FromRaw(sr.TraceState)
span.SetName(sr.Name)
span.SetKind(jptrace.StringToSpanKind(sr.Kind))
span.SetEndTimestamp(pcommon.NewTimestampFromTime(sr.StartTime.Add(time.Duration(sr.Duration))))
span.Status().SetCode(jptrace.StringToStatusCode(sr.StatusCode))
span.Status().SetMessage(sr.StatusMessage)
putAttributes(
span.Attributes(),View on GitHub (pinned to 806f444784)
Solutions
- Check the ID column value in ClickHouse for the failing row
- Ensure the ingestion path always writes a 16-hex-char span ID
- Repair or remove malformed rows
- Add a NOT NULL / format check at write time
Example fix
// before: empty ID silently stored then fails on read
// after: validate at write time
if spanID == "" { return errors.New("span ID is required") } Defensive patterns
Strategy: validation
Validate before calling
if len(sr.ID) != 16 {
return fmt.Errorf("span ID %q must be 16 hex chars before conversion", sr.ID)
} Type guard
func hasValidSpanID(sr *SpanRow) bool {
_, ok := isSpanID(sr.ID)
return ok
} Try / catch
span, err := FromRow(sr)
if err != nil && strings.Contains(err.Error(), "failed to decode span ID") {
log.Warn("skipping row with malformed span ID", "id", sr.ID)
continue
} Prevention
- Make span ID NOT NULL and format-checked at the producer
- Reject empty span IDs before INSERT
- Run periodic data-quality scans on the spans table
When it happens
Trigger: FromRow is called on a SpanRow whose ID column is empty, contains non-hex characters, or decodes to a length other than 8 bytes.
Common situations: External writers inserting rows without a span ID; encoding mismatches between producer and consumer versions; manual data fixes gone wrong.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid length %d of decoded span ID %q, expected %d bytes
- failed to decode trace ID: %w
- span ID must not be all zero
- ttl must be a non-negative duration
- ttl must be a whole number of seconds
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/f3ab737b025386bd.
Report an issue: GitHub.