jaegertracing/jaeger · error

failed to compute critical path

Error message

failed to compute critical path: %w

What it means

After successfully fetching the trace, the handler calls criticalpath.ComputeCriticalPathFromTraces; if that computation fails it wraps the error as "failed to compute critical path: <cause>". It separates analysis failures from fetch failures so callers know the trace existed but the critical path algorithm could not process it.

Solutions

  1. Inspect the wrapped cause to see which span/timing was rejected.
  2. Try a different, known-good trace ID to confirm the algorithm works and the issue is trace-specific data.
  3. Check the ingestion path that produced the trace for instrumentation bugs (invalid timestamps/durations).
  4. If reproducible on valid traces, report it with the trace ID and Jaeger version.
Defensive patterns

Strategy: fallback

Try / catch

out, err := handler.Handle(ctx, input)
if err != nil && strings.Contains(err.Error(), "failed to compute critical path:") {
    // trace fetched OK but analysis failed; fall back to returning the raw trace/span list
    return fetchRawTrace(ctx, input.TraceID)
}

Prevention

When it happens

Trigger: ComputeCriticalPathFromTraces returns an error on a retrieved trace — typically malformed or inconsistent span data (missing/unparseable timings, malformed references) retrieved by handle().

Common situations: Traces ingested by older/buggy instrumenters producing spans with invalid durations or parent references; corruption from a storage migration; traces with zero spans passing edge cases in the algorithm.

Related errors


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

Appendix: source

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

	for t, err := range aggregatedIter {
		if err != nil {
			return nil, types.GetCriticalPathOutput{}, fmt.Errorf("failed to get trace: %w", err)
		}

		traceFound = true
		trace = t
		break // We expect only one trace since we're querying by a single trace ID
	}

	if !traceFound {
		return nil, types.GetCriticalPathOutput{}, errors.New("trace not found")
	}

	// Compute critical path
	criticalPathSections, err := criticalpath.ComputeCriticalPathFromTraces(trace)
	if err != nil {
		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)

View on GitHub (pinned to 806f444784)