thanos-io/thanos · error · api.ApiError
zero or negative query resolution step widths are not…
Error message
zero or negative query resolution step widths are not accepted. Try a positive integer
What it means
In queryRange, after the step is resolved (from the `step` parameter or the default), a non-positive step is rejected with HTTP 400 (api.ErrorBadData). A zero or negative step would make point computation impossible, so the API requires a strictly positive duration. Note that parseStep's default of rangeSeconds/250 can itself round down to 0 for sub-second ranges, and an explicit `step=0` or negative value triggers this directly.
Solutions
- Pass an explicit positive step such as `step=1s` or `step=15s`.
- Validate step > 0 in the client before issuing the request.
- Widen the query range (or set an explicit step) so the default rangeSeconds/250 does not compute to 0.
Example fix
// before GET /api/v1/query_range?query=up&start=...&end=...&step=0 // after GET /api/v1/query_range?query=up&start=...&end=...&step=15s
Defensive patterns
Strategy: validation
Validate before calling
const stepMs = parseDurationMs(step); // e.g. '15s' -> 15000
if (step !== undefined && (!Number.isFinite(stepMs) || stepMs <= 0)) {
throw new Error('step must be a positive duration');
} Try / catch
const body = await res.json();
if (body.status === 'error' && /zero or negative query resolution step/.test(body.error)) {
// retry with an explicit positive step such as 1s
} Prevention
- Never send step=0 or negative steps; default to something like 15s when unset.
- For very short ranges, set an explicit step since the auto default (range/250) can round to 0.
- Clamp computed steps to a minimum of 1s in client-side helpers.
When it happens
Trigger: Calling /api/v1/query_range with `step=0`, `step=-1m`, or when the step parameter parses to a zero/negative duration; also with a very short range and no step, when the rangeSeconds/250 default computes to 0.
Common situations: Clients sending step from a variable that is empty or 0; users entering '0' in a dashboard step field; sub-second query ranges relying on the automatic default step.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
Related errors
- end timestamp must not be before start time
- could not unmarshal parameter
- engine type must be 'thanos'
- exceeded maximum resolution of 11,000 points per…
- invalid parameter ;
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/ec50035c59b12eae.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/api/query/v1.go:788
if err != nil {
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
end, err := parseTime(r.FormValue("end"))
if err != nil {
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
if end.Before(start) {
err := errors.New("end timestamp must not be before start time")
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
step, apiErr := qapi.parseStep(r, qapi.defaultRangeQueryStep, int64(end.Sub(start)/time.Second))
if apiErr != nil {
return nil, nil, apiErr, func() {}
}
if step <= 0 {
err := errors.New("zero or negative query resolution step widths are not accepted. Try a positive integer")
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
// For safety, limit the number of returned points per timeseries.
// This is sufficient for 60s resolution for a week or 1h resolution for a year.
if end.Sub(start)/step > 11000 {
err := errors.New("exceeded maximum resolution of 11,000 points per timeseries. Try decreasing the query resolution (?step=XX)")
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
ctx := r.Context()
if to := r.FormValue("timeout"); to != "" {
var cancel context.CancelFunc
timeout, err := parseDuration(to)
if err != nil {
return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err}, func() {}
}
View on GitHub (pinned to 35b8b99117)