SigNoz/signoz · error · model.ApiError

exceeded maximum resolution of 11,000 points per timeseries.

Error message

exceeded maximum resolution of 11,000 points per timeseries. Try decreasing the query resolution (?step=XX)

What it means

SigNoz caps range queries at 11,000 points per timeseries (matching Prometheus safety limits) to prevent memory exhaustion. When (end-start)/step exceeds 11000 the request is rejected and you are told to increase step.

Source

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

	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"),
	}

	return &queryRangeParams, nil
}

func parseGetUsageRequest(r *http.Request) (*model.GetUsageParams, error) {
	startTime, err := parseTime("start", r)
	if err != nil {
		return nil, err

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Increase step so that (end-start)/step <= 11000 (e.g. for 30 days use step>=240s, commonly step=5m or step=1h)
  2. Compute step dynamically from the window: step = max(minStep, window/10000)
  3. Narrow the queried time range

Example fix

// before
params.Set("step", "15s") // with a 30d range
// after
window := end.Sub(start)
step := window / 10000
if step < 15*time.Second {
    step = 15 * time.Second
}
params.Set("step", strconv.FormatInt(int64(step.Seconds()), 10))
Defensive patterns

Strategy: validation

Validate before calling

window := end.Sub(start)
step := window / 10000
if step < time.Second {
    step = time.Second
}
if window/step > 11000 {
    return fmt.Errorf("range too wide for step %v", step)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "exceeded maximum resolution") {
    // auto-retry with a coarser step
    step = window / 10000
    resp, err = api.QueryRangeMetrics(ctx, start, end, step, query)
}

Prevention

When it happens

Trigger: Querying a long window with a fine step, e.g. 30 days at step=60s (43200 points) or a year at step=1h; auto-step formulas that use a fixed small step regardless of window size.

Common situations: Dashboards with long time ranges (30d/90d) and hardcoded step=15s; custom date-pickers allowing very wide ranges; scripts that iterate with tiny steps.

Related errors


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