jaegertracing/jaeger · error

%s and %s are required

Error message

%s and %s are required

What it means

parseFindTracesQuery requires both `query.startTimeMin` and `query.startTimeMax` (RFC3339Nano bounds on trace start time). If either is absent (or empty), the request is rejected with this message naming both canonical parameter names.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/apiv3/query_parser.go:103

		queryParams.Attributes = jptrace.PlainMapToPcommonMap(attrsMap)
	}
	// The filter parameter carries a JSON-encoded expression.
	if filterParam := q.Get(paramFilter); filterParam != "" {
		var call expressionproto.Call
		if err := jsonpb.Unmarshal(strings.NewReader(filterParam), &call); err != nil {
			return nil, fmt.Errorf("malformed parameter %s: %w", paramFilter, err)
		}
		filter, err := expressionproto.FromProto(&call)
		if err != nil {
			return nil, fmt.Errorf("malformed parameter %s: %w", paramFilter, err)
		}
		queryParams.Filter = filter
	}

	timeMinStr, timeMinParam := getQueryParam(q, paramTimeMin, paramTimeMinDeprecated)
	timeMaxStr, timeMaxParam := getQueryParam(q, paramTimeMax, paramTimeMaxDeprecated)
	if timeMinStr == "" || timeMaxStr == "" {
		return nil, fmt.Errorf("%s and %s are required", paramTimeMin, paramTimeMax)
	}
	timeMinParsed, err := time.Parse(time.RFC3339Nano, timeMinStr)
	if err != nil {
		return nil, fmt.Errorf("malformed parameter %s: %w", timeMinParam, err)
	}
	timeMaxParsed, err := time.Parse(time.RFC3339Nano, timeMaxStr)
	if err != nil {
		return nil, fmt.Errorf("malformed parameter %s: %w", timeMaxParam, err)
	}
	if !timeMinParsed.Before(timeMaxParsed) {
		return nil, fmt.Errorf("%s must be before %s", paramTimeMin, paramTimeMax)
	}
	queryParams.StartTimeMin = timeMinParsed
	queryParams.StartTimeMax = timeMaxParsed

	n, searchDepthParam := getQueryParam(q, paramSearchDepth, paramSearchDepthDeprecated)
	if n == "" {
		n = q.Get(paramNumTraces)

View on GitHub (pinned to 806f444784)

Solutions

  1. Add both query.startTimeMin and query.startTimeMax as RFC3339Nano timestamps (e.g. 2026-01-01T00:00:00Z).
  2. If using the deprecated aliases (query.start_time_min/query.start_time_max), they are accepted, but must both be non-empty.
  3. If your client omits empty params, default them to a sensible window (e.g. last 24h).

Example fix

// before
GET /api/v3/traces?query.serviceName=foo
// after
GET /api/v3/traces?query.serviceName=foo&query.startTimeMin=2026-01-01T00:00:00Z&query.startTimeMax=2026-01-02T00:00:00Z
Defensive patterns

Strategy: validation

Validate before calling

func ensureTimeRange(params url.Values) error {
	if params.Get("query.startTimeMin") == "" || params.Get("query.startTimeMax") == "" {
		return errors.New("query.startTimeMin and query.startTimeMax are required")
	}
	return nil
}

Try / catch

if resp.StatusCode == 400 {
	return fmt.Errorf("time range required: %s", mustRead(resp.Body))
}

Prevention

When it happens

Trigger: GET /api/v3/traces or /api/v3/traces/summaries without query.startTimeMin, without query.startTimeMax, or supplying only one of the two; also when supplying only deprecated snake_case aliases that are empty strings.

Common situations: Clients assuming time range is optional as in older Jaeger APIs; query builders omitting empty time bounds; migrations from snake_case params where the canonical camelCase params were never sent.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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