PRQL/prql · error · Error
parameter `rows`: expected a range, found
Error message
parameter `rows`: expected a range, found {found} What it means
The `rows` parameter of the `window` transform expects a range (a tuple of two bounds, e.g. `(2..4)`) describing the frame in rows. The resolver runs `try_restrict_range` on the argument and throws this error when the argument cannot be interpreted as a range.
Solutions
- Pass a range tuple with both bounds, e.g. `rows:(-2..4)`
- Use `..` range syntax rather than brackets or commas
- For a symmetric frame use `rolling:` instead, or unbounded sides like `rows:(..4)`
Example fix
// before window rows:[2,4] (sum amount) // after window rows:(2..4) (sum amount)
Defensive patterns
Strategy: validation
Validate before calling
const rows = "(-2..4)"; // must be a PRQL range tuple
if (!/^\(-?[\w]+\.\.-?[\w]+\)$/.test(rows)) {
throw new Error("rows must be a range like (start..end)");
} Type guard
const isRangeArg = (v) => typeof v === "object" && v !== null && "start" in v && "end" in v;
Try / catch
try { prql_compile(query); } catch (e) { if (e.message.includes("parameter `rows`")) { /* convert arg to a range tuple */ } else { throw e; } } Prevention
- Always use (start..end) range syntax
- Never pass a single number or a list for rows
- Use rolling: for fixed-size frames instead
When it happens
Trigger: Calling `window rows:<x>` where `<x>` is not a range tuple — e.g. `rows:3` (single number), `rows:[2,4]` (list instead of range), or a non-literal expression.
Common situations: Porting SQL `ROWS BETWEEN 2 PRECEDING AND 4 FOLLOWING` without converting to PRQL range syntax; passing a single bound; using array/tuple braces incorrectly.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- parameter `range`: expected a range, found
- parameter `expanding`: expected a boolean, found
- parameter `rolling`: expected a number, found
- take: expected a positive int range, found
- `side`: expected inner, left, right or full, found
AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09).
Data as JSON: /api/errors/75a9c563b1120747.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:191
})?
};
let rolling = {
let as_int = rolling.kind.as_literal().and_then(|x| x.as_integer());
*as_int.ok_or_else(|| {
Error::new(Reason::Expected {
who: Some("parameter `rolling`".to_string()),
expected: "a number".to_string(),
found: write_pl(rolling.clone()),
})
.with_span(rolling.span)
})?
};
let rows = {
let range_tuple = try_restrict_range(rows).map_err(|expr| {
Error::new(Reason::Expected {
who: Some("parameter `rows`".to_string()),
expected: "a range".to_string(),
found: write_pl(expr.clone()),
})
.with_span(expr.span)
})?;
into_literal_range(range_tuple)?
};
let range = {
let range_tuple = try_restrict_range(range).map_err(|expr| {
Error::new(Reason::Expected {
who: Some("parameter `range`".to_string()),
expected: "a range".to_string(),
found: write_pl(expr.clone()),
})
.with_span(expr.span)
})?;View on GitHub (pinned to e164e249b9)