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

  1. Check the ID column value in ClickHouse for the failing row
  2. Ensure the ingestion path always writes a 16-hex-char span ID
  3. Repair or remove malformed rows
  4. 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

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

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/f3ab737b025386bd. Report an issue: GitHub.