jaegertracing/jaeger · error
trace ID must be 32 hex characters, got %d
Error message
trace ID must be 32 hex characters, got %d
What it means
parseTraceID is the low-level helper behind the "invalid trace_id" wrap: it enforces that a trace ID string is exactly 32 hex characters (16 bytes / 128 bits), the W3C Trace Context width Jaeger uses. When the length check fails it emits this message with the actual length; a subsequent hex decode failure yields a separate "invalid hex string" error.
Source
Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/internal/handlers/get_span_details.go:275
}
return result
case pcommon.ValueTypeMap:
m := v.Map()
result := make(map[string]any)
for k, v := range m.All() {
result[k] = convertAttributeValue(v)
}
return result
default:
return nil
}
}
// parseTraceID parses a trace ID string into a pcommon.TraceID.
func parseTraceID(traceIDStr string) (pcommon.TraceID, error) {
// Parse hex string - TraceID is 16 bytes (32 hex characters)
if len(traceIDStr) != 32 {
return pcommon.TraceID{}, fmt.Errorf("trace ID must be 32 hex characters, got %d", len(traceIDStr))
}
var traceID pcommon.TraceID
bytes, err := hex.DecodeString(traceIDStr)
if err != nil {
return pcommon.TraceID{}, fmt.Errorf("invalid hex string: %w", err)
}
copy(traceID[:], bytes)
return traceID, nil
}
// parseSpanID parses a span ID string into a pcommon.SpanID.
func parseSpanID(spanIDStr string) (pcommon.SpanID, error) {
// Parse hex string - SpanID is 8 bytes (16 hex characters)
if len(spanIDStr) != 16 {
return pcommon.SpanID{}, fmt.Errorf("span ID must be 16 hex characters, got %d", len(spanIDStr))
}View on GitHub (pinned to 806f444784)
Solutions
- Ensure the string is exactly 32 characters before calling; left-pad with zeros if it is 16.
- Normalize: strip 0x, dashes, whitespace, and re-check len == 32.
- Keep IDs as canonical lowercase hex throughout your pipeline.
- Wrap your own calls with a length check and pad rather than passing through raw user/log output.
Example fix
// before
id := traceIDString() // "e8d3fbe4e0b6e0f2" (16 chars)
parseTraceID(id) // -> "trace ID must be 32 hex characters, got 16"
// after
id := fmt.Sprintf("%032s", traceIDString())
parseTraceID(id) // ok Defensive patterns
Strategy: validation
Validate before calling
func ensureTraceID(s string) (string, error) {
s = strings.ToLower(strings.TrimPrefix(strings.TrimSpace(s), "0x"))
if len(s) == 16 { s = strings.Repeat("0", 16) + s }
if len(s) != 32 {
return "", fmt.Errorf("trace ID must be 32 hex characters, got %d", len(s))
}
if _, err := hex.DecodeString(s); err != nil { return "", err }
return s, nil
} Type guard
func is32Hex(s string) bool {
return len(s) == 32 && func() bool { _, err := hex.DecodeString(s); return err == nil }()
} Try / catch
id, err := ensureTraceID(raw)
if err != nil {
if strings.Contains(err.Error(), "must be 32 hex characters") {
raw = fmt.Sprintf("%032s", strings.TrimPrefix(raw, "0x"))
id, err = ensureTraceID(raw)
}
} Prevention
- Centralize trace ID formatting in one normalize helper that pads to 32 chars.
- Keep IDs as canonical lowercase hex end-to-end.
- Guard against truncation when logging or copying IDs between systems.
- Distinguish length errors (this message) from hex-decode errors ("invalid hex string") when diagnosing.
When it happens
Trigger: Any call path reaching parseTraceID (buildQuery for span details, or the anonymous wrapper) with a trace ID string whose len != 32 — e.g. 16-char legacy IDs, IDs with a 0x prefix or dashes altering length, or truncated IDs.
Common situations: W3C 8-byte trace IDs from instrumented apps stored unpadded; string manipulation that truncated or concatenated IDs; IDs obtained from OTLP JSON with different encoding.
Related errors
- invalid trace_id: %w
- trace_id is required
- start_time must be before end_time
- trace_id is required
- span_ids is required and must not be empty
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/8a9e044aa0ac9411.
Report an issue: GitHub.