Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Grafana By James Joyner IV · · 8 min read

Grafana Error Guide: 'input data must be a wide series but got type long' — Fix Alert Expressions

Quick answer

Fix Grafana unified alerting 'input data must be a wide series but got type long': add a reduce stage, fix the query frame format, and structure math/threshold expressions correctly.

  • #grafana
  • #observability
  • #troubleshooting
  • #errors
Free toolkit

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’s unified alerting evaluates a rule as a pipeline of stages: a datasource query produces a data frame, and server-side expressions (reduce, math, threshold, resample) transform it into the single scalar-per-series that the alert condition needs. Each expression type expects its input in a specific frame format — “wide” (a time column plus one value column per series) versus “long” (a tall table with label columns and one value column). When a stage receives the wrong format, evaluation aborts with a type error and the rule shows “Error” instead of a real state.

The literal errors you will see in the alert rule’s state or Grafana’s log:

input data must be a wide series but got type long (input refid)
[sse.dataplane] error: input data must be a wide series but got type long
failed to execute conditions: input data must be a wide series but got type long (A)

The tell: the failing refid (e.g. A) points at the query or the stage feeding your math/threshold, and the words are “wide” vs “long” — a frame-format mismatch, not a query syntax error.

Symptoms

  • An alert rule’s state is “Error”, not Alerting/OK, right after you build or import it.
  • “Preview alert” or “Test rule” fails immediately with the wide/long message.
  • SQL, Loki, CloudWatch Logs, or Elasticsearch queries feeding a math/threshold trigger it more than Prometheus.
  • The same query renders fine in a panel but fails as an alert condition.
  • Provisioned rules load but every evaluation errors.

Common Root Causes

1. Math/threshold reads a raw query instead of a reduced value

math, threshold, and classic_condition expect a reduced scalar per series (wide). Pointing them straight at a time-series query (or a long-format table) causes the type error.

2. A “long” frame from SQL / logs datasources

SQL, Loki, and log-based queries commonly return long frames (label columns + value). Alerting expressions want wide frames, so a reduce/format step is required first.

3. Missing reduce stage

The query returns a full time series; without a reduce (last/mean/max) collapsing it to one value per series, the downstream expression gets a series where it expects a number.

4. instant: false where an instant vector was intended

A range query returns many points per series (a series frame); the condition expects the latest value.

5. Multi-frame / mixed-shape query output

A query emitting multiple frames of differing shape (some wide, some long) makes the expression engine reject the input.

Diagnostic Workflow

Step 1: Find the failing refid and inspect the frame

In the rule editor, run each stage and read which refid errors. Then look at the raw frame the query returns:

# Query the datasource resource the way alerting does, and inspect the frame schema
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  http://localhost:3000/api/ds/query \
  -d '{"queries":[{"refId":"A","datasourceUid":"prometheus-prod","expr":"up","instant":true}]}' \
  | jq '.results.A.frames[].schema.meta.type, .results.A.frames[].schema.fields[].type'

A numeric wide frame is what expressions want; a timeSeriesLong/table shape needs reducing first.

Step 2: Add the missing reduce stage

Insert a reduce expression between the query and the math/threshold. In the UI this is “Reduce → Function: Last → Input: A”. As provisioning YAML:

data:
  - refId: A
    datasourceUid: prometheus-prod
    relativeTimeRange: { from: 300, to: 0 }
    model:
      expr: sum(rate(http_requests_total{code=~"5.."}[5m]))
      instant: false
  - refId: B
    datasourceUid: __expr__
    model:
      type: reduce
      expression: A
      reducer: last
  - refId: C
    datasourceUid: __expr__
    model:
      type: threshold
      expression: B
      conditions:
        - evaluator: { type: gt, params: [1] }

The condition is C, fed by the reduced value B, not raw A.

Step 3: Convert long frames to wide (SQL / logs)

For SQL, shape the query so it returns one numeric value per series (a wide/numeric frame) — select an aggregate, not a raw table:

-- Returns a single reducible value per group, not a long table
SELECT service, avg(latency_ms) AS value
FROM requests
WHERE ts > now() - interval '5 minutes'
GROUP BY service

Then still add a reduce (Last) before the threshold if the frame carries a time dimension.

Step 4: Use an instant query where appropriate

For Prometheus alert conditions, an instant vector plus a reduce is the cleanest path:

model:
  expr: sum by (job) (rate(http_requests_total{code=~"5.."}[5m]))
  instant: true

Step 5: Verify the rule evaluates cleanly

# List rule state after saving; look for "Error" vs "Normal"/"Alerting"
curl -s -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/prometheus/grafana/api/v1/rules \
  | jq '.data.groups[].rules[] | {name, state, health}'

# Provisioning + alerting evaluation errors
journalctl -u grafana-server | grep -iE "ngalert|sse.dataplane|wide series"

Example Root Cause Analysis

An engineer imported an alert rule that queried sum(rate(http_requests_total{code=~"5.."}[5m])) and wired a threshold > 1 directly to the query’s refid A. The rule saved but every evaluation showed “Error” with input data must be a wide series but got type long (A).

Inspecting the frame via /api/ds/query showed the query returned a time-series frame (many points), while threshold expects one reduced value per series. There was no reduce stage — the threshold was reading a raw series where it needed a scalar.

Fix: insert a reduce (Function: Last) as refid B between the query and the threshold, and set the rule condition to the threshold refid C fed by B. The rule immediately evaluated to a real Normal/Alerting state. The root cause was a missing reduce stage, not the PromQL — the query itself was fine; its shape was wrong for the expression that consumed it.

Prevention Best Practices

  • Always structure alert rules as query → reducemath/threshold, with the condition on the final expression, not the raw query; see more Grafana guides.
  • For SQL and log datasources, return an aggregated numeric value per series so frames are reducible, not long tables.
  • Prefer instant queries for Prometheus alert conditions, then reduce.
  • Test every rule with “Preview alert” before saving; a “wide series” error surfaces there instantly.
  • When provisioning rules as code, template the reduce/threshold stages so authors can’t skip the reduce.
  • Triage recurring alerting evaluation errors with the free monitoring assistant.

Quick Command Reference

# Inspect the frame type a query returns
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  http://localhost:3000/api/ds/query \
  -d '{"queries":[{"refId":"A","datasourceUid":"<uid>","expr":"<query>","instant":true}]}' \
  | jq '.results.A.frames[].schema.meta.type'

# Rule state after fixing (Error vs Normal/Alerting)
curl -s -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/prometheus/grafana/api/v1/rules \
  | jq '.data.groups[].rules[] | {name, state, health}'

# Evaluation errors in logs
journalctl -u grafana-server | grep -iE "ngalert|wide series"

Conclusion

“Input data must be a wide series but got type long” is a frame-format mismatch inside the alert expression pipeline. Fix it in order:

  1. Find the failing refid and inspect the frame the query returns (wide/numeric vs long).
  2. Insert a reduce (Last/Mean) so the downstream math/threshold gets one value per series.
  3. For SQL/log datasources, aggregate the query so it returns a reducible numeric frame.
  4. Point the rule condition at the final expression, not the raw query, and preview before saving.

Structuring every rule as query → reduce → threshold removes the cause; skipping the reduce is what produces the error.

Free download · 368-page PDF

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.