jaegertracing/jaeger · error

trace ID must be 16 bytes, got %d

Error message

trace ID must be 16 bytes, got %d

What it means

After successful hex decoding, traceIDFromHex verifies the decoded byte slice is exactly 16 bytes, as required by pcommon.TraceID. A shorter or longer (but still valid hex) string is rejected with 'trace ID must be 16 bytes, got %d'. A 32-hex-char string decodes to exactly 16 bytes, so this fires for hex strings of any other even length.

Source

Thrown at cmd/jaeger/internal/integration/trace_reader.go:290

}

func unwrapNotFoundErr(err error) error {
	if s, _ := status.FromError(err); s != nil {
		if strings.Contains(s.Message(), spanstore.ErrTraceNotFound.Error()) {
			return spanstore.ErrTraceNotFound
		}
	}
	return err
}

// traceIDFromHex parses a 32-character hex string into a pcommon.TraceID.
func traceIDFromHex(s string) (pcommon.TraceID, error) {
	b, err := hex.DecodeString(s)
	if err != nil {
		return pcommon.TraceID{}, fmt.Errorf("invalid trace ID %q: %w", s, err)
	}
	if len(b) != 16 {
		return pcommon.TraceID{}, fmt.Errorf("trace ID must be 16 bytes, got %d", len(b))
	}
	return pcommon.TraceID(b), nil
}

View on GitHub (pinned to 806f444784)

Solutions

  1. Ensure the input is exactly 32 hex characters before calling; trim or validate length
  2. If you have a span ID (16 hex chars), do not feed it as a trace ID — use the correct field
  3. For variable-length sources, pad/left-align legacy 8-byte trace IDs to 16 bytes only if that is the intended semantic

Example fix

// before
traceID, err := traceIDFromHex(spanIDHex) // 16 hex chars = 8 bytes
// after
if len(traceIDHex) != 32 {
    return fmt.Errorf("trace ID must be 32 hex chars, got %d", len(traceIDHex))
}
traceID, err := traceIDFromHex(traceIDHex)
Defensive patterns

Strategy: validation

Validate before calling

func hasTraceIDLength(s string) bool { return len(s) == 32 } // 32 hex chars == 16 bytes

Try / catch

tid, err := traceIDFromHex(s)
if err != nil {
    if strings.HasPrefix(err.Error(), "trace ID must be 16 bytes") {
        return fmt.Errorf("%q is not a trace ID (span ID or foreign ID?)", s)
    }
    return err
}

Prevention

When it happens

Trigger: Parsing a hex string like 16 or 64 hex characters that decodes cleanly but is not 16 bytes — e.g. span IDs (8 bytes) passed where trace IDs are expected, or concatenated trace+span IDs.

Common situations: Passing a span ID instead of a trace ID; pasting a 64-hex-char 128-bit trace ID from another tracing system (W3C allows 16-byte, but 8-byte IDs from legacy systems are common); slicing errors in test data generators.

Related errors


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