SigNoz/signoz · error · model.ApiError

zero or negative query resolution step widths are not accept

Error message

zero or negative query resolution step widths are not accepted. Try a positive integer

What it means

The range query parser requires a strictly positive step (query resolution). A step of zero or negative would cause infinite points or division issues, so SigNoz (like Prometheus) rejects it with ErrorBadData.

Source

Thrown at pkg/query-service/app/parser.go:158

	if err != nil {
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}
	end, err := parseMetricsTime(r.FormValue("end"))
	if err != nil {
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}
	if end.Before(start) {
		err := errors.New("end timestamp must not be before start time")
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}

	step, err := parseMetricsDuration(r.FormValue("step"))
	if err != nil {
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}

	if step <= 0 {
		err := errors.New("zero or negative query resolution step widths are not accepted. Try a positive integer")
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}

	// 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, &model.ApiError{Typ: model.ErrorBadData, Err: err}
	}

	queryRangeParams := model.QueryRangeParams{
		Start: start,
		End:   end,
		Step:  step,
		Query: r.FormValue("query"),
		Stats: r.FormValue("stats"),
	}

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Set an explicit positive step such as step=15s or step=60
  2. Fix client-side step math: guard against division by zero and round up to at least 1 second
  3. Regenerate the URL after fixing the step parameter and retry

Example fix

// before
step := int(end.Sub(start).Seconds()) / numPoints // numPoints==0 -> 0
// after
if numPoints <= 0 {
    numPoints = 100
}
step := int(end.Sub(start).Seconds()) / numPoints
if step < 1 {
    step = 1
}
Defensive patterns

Strategy: validation

Validate before calling

stepDur, err := time.ParseDuration(stepStr)
if err != nil || stepDur <= 0 {
    stepDur = 60 * time.Second
}
resp, err := api.QueryRangeMetrics(ctx, start, end, stepDur, query)

Prevention

When it happens

Trigger: GET query_range with step=0, step=-15s, or a step string that parses to a zero duration (e.g. step=0s), or omitting calculations that default step to 0 in generated URLs.

Common situations: Dashboards computing step as (end-start)/N where N=0 or integer division truncates to 0; hardcoded step variables; migrating queries from systems where step=0 meant auto.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/3b8695225bd11fef. Report an issue: GitHub.