Grafana Error Guide: 'interval must be greater than 0' — Fix Panel and Variable Intervals
Fix Grafana 'interval must be greater than 0' panel errors: correct min interval and interval variables, fix $__interval, and resolve zero-step queries.
- #grafana
- #observability
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Grafana (or its datasource backend) raises this when a query’s step/interval resolves to zero or a non-positive duration, so the time-series engine can’t build a range vector. The panel shows:
interval must be greater than 0
Prometheus-backed variants of the same underlying problem read:
invalid parameter "step": zero or negative query resolution step widths are not accepted
error parsing range query: interval 0s is not valid
In every case the computed step — from $__interval, $__rate_interval, a “Min interval” panel setting, or an interval-type template variable — came out as 0s, which no time-series datasource will accept.
Symptoms
- One panel errors with
interval must be greater than 0while others on the dashboard render fine. - The error appears only at certain zoom levels or on a very small/large time range.
- It started after adding an interval template variable or editing the panel’s Min interval.
- Prometheus/Loki return the
stepvariant while the same query works in the Explore view with a manual step. - A
$__interval/$intervaltoken appears literally unresolved in the query inspector.
Common Root Causes
- An interval-type template variable with an empty or malformed value, so
$intervalexpands to nothing or0s. - “Min interval” set to
0, blank, or a bad unit (0,s,1without a unit) in the panel/datasource query options. - A range vector using
[$__interval]when$__intervalresolves to0s— tiny time range over hugemaxDataPoints, ormaxDataPointsset to 0. - A custom variable feeding
stepwhose current value is empty (no default selected). - Hardcoded
[0s]orrate(...[$interval])where the variable never got a value. - Datasource
timeIntervalunset so Grafana can’t floor$__intervalto a sane minimum.
Diagnostic Workflow
1. Read the resolved query, not the template. The query inspector shows what actually went to the datasource:
Panel → Inspect → Query → expand the request
Look for step=0, [0s], or an unexpanded $interval token — that pinpoints which interval is zero.
2. Check the interval template variable. If the panel uses $interval, confirm the variable is an Interval type with real values and a selected default:
Dashboard settings → Variables → <interval var>
Type: Interval
Values: 1m,5m,10m,30m,1h
Auto option: on (Step count e.g. 30)
An interval variable with no selected value expands to empty → 0s.
3. Set a valid “Min interval”. In the panel’s query options, set Min interval to the real scrape interval (never 0):
Query options → Min interval: 15s
Max data points: (leave default / >0)
4. Set the datasource timeInterval so $__interval/$__rate_interval always floor to a positive value. Provisioned:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
jsonData:
timeInterval: 15s # floors $__interval; prevents 0s steps
5. Prefer $__rate_interval over $__interval in rate()/irate() so the step is always at least the scrape interval:
rate(http_requests_total{job="$job"}[$__rate_interval])
6. Reproduce against the backend to confirm the fix resolves a positive step:
# A valid, positive step succeeds
curl -s -G http://prometheus:9090/api/v1/query_range \
--data-urlencode 'query=up' --data-urlencode 'start=1720000000' \
--data-urlencode 'end=1720003600' --data-urlencode 'step=15' | jq '.status'
# step=0 returns the "zero or negative ... step" error
Example Root Cause Analysis
A dashboard added a template variable $interval to let users pick the aggregation window, and one time-series panel then failed with interval must be greater than 0 — but only for users opening the board via a shared link.
The query inspector showed the request going out with [0s] in the range vector. The $interval variable was defined as an Interval type but had no default value selected; interactive users happened to pick one, so it worked for them, while the shared link loaded the variable empty, expanding $interval to nothing and the range to [0s].
Fix: set a default value on the interval variable (5m) and enabled the Auto option with a sensible step count, and set the datasource timeInterval: 15s as a floor. The panel rendered for everyone, including cold shared-link loads. The zero step was purely an unset variable default, not a query bug.
Prevention Best Practices
- Give every interval template variable a default value and enable the Auto option so it never expands to empty.
- Set a datasource
timeIntervalmatching the scrape interval to floor$__intervalabove zero. - Set a non-zero “Min interval” on panels that aggregate, rather than leaving it blank.
- Use
$__rate_intervalforrate()so the step is always at least one scrape. - Keep
maxDataPointsat its default (or >0); a zero there can drive$__intervalto0s. - Test dashboards via a cold shared link, not just interactively, so unset variable defaults surface before users hit them.
Quick Command Reference
# Inspect the resolved request (UI): Panel → Inspect → Query
# Confirm a positive step works against Prometheus
curl -s -G http://prometheus:9090/api/v1/query_range \
--data-urlencode 'query=up' --data-urlencode 'step=15' \
--data-urlencode 'start=1720000000' --data-urlencode 'end=1720003600' | jq '.status'
# Verify the datasource timeInterval floor
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
http://localhost:3000/api/datasources/name/Prometheus | jq '.jsonData.timeInterval'
Conclusion
interval must be greater than 0 means the query’s computed step resolved to 0s — almost always an interval template variable with no default, a blank “Min interval”, or a missing datasource timeInterval. Read the resolved request in the query inspector to see which interval is zero, give interval variables a default, floor $__interval with timeInterval, and prefer $__rate_interval for rates. Testing via a cold shared link catches the unset-default case before users do.
More Grafana prompts & error guides
Every Grafana AI prompt and troubleshooting guide, in one place.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.