jaegertracing/jaeger · error
start_time must be before end_time
Error message
start_time must be before end_time
What it means
The get_dependencies MCP handler parses start_time and end_time (with defaults when empty) and requires start to be strictly before end. This error is thrown when startTime >= endTime, because GetDependencies takes an end timestamp plus a lookback duration — a non-positive lookback is meaningless.
Source
Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/internal/handlers/get_dependencies.go:57
func (h *getDependenciesHandler) handle(
ctx context.Context,
_ *mcp.CallToolRequest,
input types.GetDependenciesInput,
) (*mcp.CallToolResult, types.GetDependenciesOutput, error) {
endTime, err := parseDependencyTime(input.EndTime, time.Now())
if err != nil {
return nil, types.GetDependenciesOutput{}, fmt.Errorf("invalid end_time: %w", err)
}
defaultStart := endTime.Add(-24 * time.Hour)
startTime, err := parseDependencyTime(input.StartTime, defaultStart)
if err != nil {
return nil, types.GetDependenciesOutput{}, fmt.Errorf("invalid start_time: %w", err)
}
if !startTime.Before(endTime) {
return nil, types.GetDependenciesOutput{}, errors.New("start_time must be before end_time")
}
lookback := endTime.Sub(startTime)
deps, err := h.queryService.GetDependencies(ctx, endTime, lookback)
if err != nil {
return nil, types.GetDependenciesOutput{}, fmt.Errorf("failed to get dependencies: %w", err)
}
links := make([]types.DependencyLink, 0, len(deps))
for _, d := range deps {
links = append(links, types.DependencyLink{
Caller: d.Parent,
Callee: d.Child,
CallCount: d.CallCount,
})
}
// Sort by caller then callee for consistent orderingView on GitHub (pinned to 806f444784)
Solutions
- Ensure start_time < end_time before calling; swap the values if reversed
- Omit both fields to use the handler's sensible defaults
- Normalize both timestamps to the same timezone/unit (RFC3339) before passing them
Example fix
// before
input := types.GetDependenciesInput{StartTime: end, EndTime: start} // swapped
// after
if start.After(end) {
start, end = end, start
}
input := types.GetDependenciesInput{StartTime: start, EndTime: end} Defensive patterns
Strategy: validation
Validate before calling
start, err1 := time.Parse(time.RFC3339, input.StartTime)
end, err2 := time.Parse(time.RFC3339, input.EndTime)
if err1 != nil || err2 != nil { return errors.New("bad timestamps") }
if !start.Before(end) { return errors.New("start_time must be before end_time") } Try / catch
out, err := handler.Handle(ctx, req, input)
if err != nil && strings.Contains(err.Error(), "start_time must be before end_time") {
// swap or clamp the range and retry once
input.StartTime, input.EndTime = input.EndTime, input.StartTime
out, err = handler.Handle(ctx, req, input)
} Prevention
- Always parse and normalize both timestamps to RFC3339 UTC before sending
- Assert start < end in unit tests for any time-range helper
- Beware timezone and unit (s vs ms) conversions when constructing ranges
When it happens
Trigger: Passing start_time >= end_time, e.g. swapped RFC3339 values, same timestamp for both, or a custom end_time earlier than the parsed default start; also when a user passes only end_time earlier than the default lookback start.
Common situations: Reversed argument order (start/end swapped); timezone offsets making the intended order flip after parsing; milliseconds-vs-seconds unit confusion; an LLM generating end before start.
Related errors
- trace_id is required
- trace_id is required
- span_ids is required and must not be empty
- span ID must not be all zero
- service_name is required
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/bb3d6932f0447a2c.
Report an issue: GitHub.