jaegertracing/jaeger · error

invalid trace_id: %w

Error message

invalid trace_id: %w

What it means

buildQuery parses the user-supplied trace ID string with parseTraceID; a parse failure is wrapped as "invalid trace_id: <cause>". The MCP tool requires an exact, well-formed trace ID (e.g. 32 hex chars for a 128-bit ID) to query the trace store.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/internal/handlers/get_critical_path.go:99

		return nil, types.GetCriticalPathOutput{}, fmt.Errorf("failed to compute critical path: %w", err)
	}

	// Build output
	output := h.buildOutput(input.TraceID, trace, criticalPathSections)

	return nil, output, nil
}

// buildQuery converts GetCriticalPathInput to querysvc.GetTraceParams.
func (*getCriticalPathHandler) buildQuery(input types.GetCriticalPathInput) (querysvc.GetTraceParams, error) {
	// Validate input
	if input.TraceID == "" {
		return querysvc.GetTraceParams{}, errors.New("trace_id is required")
	}

	traceID, err := parseTraceID(input.TraceID)
	if err != nil {
		return querysvc.GetTraceParams{}, fmt.Errorf("invalid trace_id: %w", err)
	}

	return querysvc.GetTraceParams{
		TraceIDs: []tracestore.GetTraceParams{
			{TraceID: traceID},
		},
		RawTraces: false, // We want adjusted traces
	}, nil
}

// buildOutput constructs the GetCriticalPathOutput from the trace and critical path sections.
func (*getCriticalPathHandler) buildOutput(
	traceIDStr string,
	trace ptrace.Traces,
	criticalPathSections []criticalpath.Section,
) types.GetCriticalPathOutput {
	// Build a map of spans for quick lookup
	spanMap := jptrace.SpanMap(trace, func(span ptrace.Span) string {

View on GitHub (pinned to 806f444784)

Solutions

  1. Pass the full 128-bit trace ID as lowercase hex (32 characters) from the trace's header, not a span ID or shortened form.
  2. Strip whitespace/quotes and any composite suffixes (e.g. ':spanid') from the ID.
  3. Re-copy the trace ID from the Jaeger UI or the storage record to avoid transcription errors.

Example fix

// before
{"trace_id": "abc123"}
// after
{"trace_id": "4e7a1f2b3c4d5e6f708192a3b4c5d6e7"}
Defensive patterns

Strategy: validation

Validate before calling

func validTraceID(s string) bool {
    s = strings.TrimSpace(s)
    if len(s) != 32 && len(s) != 16 { return false }
    _, err := hex.DecodeString(s)
    return err == nil
}
if !validTraceID(input.TraceID) { return errors.New("trace_id must be 16 or 32 hex characters") }

Type guard

func isHexString(s string, l int) bool {
    return len(s) == l && strings.TrimFunc(strings.ToLower(s), func(r rune) bool {
        return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f')
    }) == ""
}

Try / catch

out, err := handler.Handle(ctx, input)
if err != nil && strings.Contains(err.Error(), "invalid trace_id:") {
    return fmt.Errorf("supply the full 32-char hex trace ID: %w", err)
}

Prevention

When it happens

Trigger: Calling the get_critical_path tool with a trace_id that is empty (a separate 'trace_id is required' error), non-hexadecimal, wrong length, or otherwise unparseable by parseTraceID.

Common situations: LLM/MCP client passes a display ID, span ID, or truncated trace ID copied from a UI; whitespace or URL-encoding artifacts in the string; passing a Jaeger 'traceid:spanid' composite string.

Related errors


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