jaegertracing/jaeger · error

duration_max must be greater than duration_min

Error message

duration_max must be greater than duration_min

What it means

search_traces' buildQuery parses duration_min and duration_max with time.ParseDuration and rejects a query where both are set and duration_max is smaller than duration_min. Such a duration window is empty and can never match, so the error prevents a guaranteed-empty search. Like the time-range check, it fires before any storage call.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/internal/handlers/search_traces.go:160

		return querysvc.TraceQueryParams{}, errors.New("start_time_max must be after start_time_min")
	}

	var durationMin, durationMax time.Duration
	if input.DurationMin != "" {
		durationMin, err = time.ParseDuration(input.DurationMin)
		if err != nil {
			return querysvc.TraceQueryParams{}, fmt.Errorf("invalid duration_min: %w", err)
		}
	}
	if input.DurationMax != "" {
		durationMax, err = time.ParseDuration(input.DurationMax)
		if err != nil {
			return querysvc.TraceQueryParams{}, fmt.Errorf("invalid duration_max: %w", err)
		}
	}

	if durationMin > 0 && durationMax > 0 && durationMax < durationMin {
		return querysvc.TraceQueryParams{}, errors.New("duration_max must be greater than duration_min")
	}

	const defaultSearchDepth = 10
	searchDepth := input.SearchDepth
	if searchDepth <= 0 {
		searchDepth = defaultSearchDepth
	}
	if searchDepth > h.maxResults {
		searchDepth = h.maxResults
	}

	attributes := pcommon.NewMap()
	for key, value := range input.Attributes {
		attributes.PutStr(key, value)
	}
	if input.WithErrors {
		attributes.PutStr("error", "true")
	}

View on GitHub (pinned to 806f444784)

Solutions

  1. Swap the duration_min/duration_max values so max is greater than min.
  2. Double-check the Go duration units on both values (ms vs s vs m) — unit mistakes silently change magnitude.
  3. Parse both values with time.ParseDuration client-side and assert max > min before calling the tool.

Example fix

// before
types.SearchTracesInput{DurationMin: "2s", DurationMax: "500ms"} // inverted
// after
minD, _ := time.ParseDuration("500ms")
maxD, _ := time.ParseDuration("2s")
if minD >= maxD {
    minD, maxD = maxD, minD
}
types.SearchTracesInput{DurationMin: minD.String(), DurationMax: maxD.String()}
Defensive patterns

Strategy: validation

Validate before calling

minD, err := time.ParseDuration(input.DurationMin); if err != nil { return err }
maxD, err := time.ParseDuration(input.DurationMax); if err != nil { return err }
if maxD < minD {
    return fmt.Errorf("duration_max (%s) must be >= duration_min (%s)", maxD, minD)
}

Try / catch

out, err := handler.Handle(ctx, in)
if err != nil {
    if strings.Contains(err.Error(), "duration_max must be greater") {
        in.DurationMin, in.DurationMax = in.DurationMax, in.DurationMin
        return handler.Handle(ctx, in)
    }
    return err
}

Prevention

When it happens

Trigger: Calling the search_traces MCP tool with duration_max < duration_min (e.g. duration_min="1s", duration_max="500ms"), or passing values in mismatched units so the parsed max ends up smaller ("2ms" vs "1s").

Common situations: Swapped min/max fields in the request; unit confusion where one value is milliseconds and the other seconds (Go durations require explicit units like 100ms, 2s); a dashboard passing user-supplied bounds without validating order.

Related errors


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