{"record":{"id":"75a9c563b1120747","repo":"PRQL/prql","slug":"parameter-rows-expected-a-range-found-found","errorCode":null,"errorMessage":"parameter `rows`: expected a range, found {found}","messagePattern":"parameter `rows`: expected a range, found (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"prqlc/prqlc/src/semantic/resolver/transforms.rs","lineNumber":191,"sourceCode":"                    })?\n                };\n\n                let rolling = {\n                    let as_int = rolling.kind.as_literal().and_then(|x| x.as_integer());\n\n                    *as_int.ok_or_else(|| {\n                        Error::new(Reason::Expected {\n                            who: Some(\"parameter `rolling`\".to_string()),\n                            expected: \"a number\".to_string(),\n                            found: write_pl(rolling.clone()),\n                        })\n                        .with_span(rolling.span)\n                    })?\n                };\n\n                let rows = {\n                    let range_tuple = try_restrict_range(rows).map_err(|expr| {\n                        Error::new(Reason::Expected {\n                            who: Some(\"parameter `rows`\".to_string()),\n                            expected: \"a range\".to_string(),\n                            found: write_pl(expr.clone()),\n                        })\n                        .with_span(expr.span)\n                    })?;\n                    into_literal_range(range_tuple)?\n                };\n\n                let range = {\n                    let range_tuple = try_restrict_range(range).map_err(|expr| {\n                        Error::new(Reason::Expected {\n                            who: Some(\"parameter `range`\".to_string()),\n                            expected: \"a range\".to_string(),\n                            found: write_pl(expr.clone()),\n                        })\n                        .with_span(expr.span)\n                    })?;","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/PRQL/prql/blob/e164e249b99485890036eb60f57c37520379b240/prqlc/prqlc/src/semantic/resolver/transforms.rs#L173-L209","documentation":"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.","triggerScenarios":"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.","commonSituations":"Porting SQL `ROWS BETWEEN 2 PRECEDING AND 4 FOLLOWING` without converting to PRQL range syntax; passing a single bound; using array/tuple braces incorrectly.","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)`"],"exampleFix":"// before\nwindow rows:[2,4] (sum amount)\n// after\nwindow rows:(2..4) (sum amount)","handlingStrategy":"validation","validationCode":"const rows = \"(-2..4)\"; // must be a PRQL range tuple\nif (!/^\\(-?[\\w]+\\.\\.-?[\\w]+\\)$/.test(rows)) {\n  throw new Error(\"rows must be a range like (start..end)\");\n}","typeGuard":"const isRangeArg = (v) => typeof v === \"object\" && v !== null && \"start\" in v && \"end\" in v;","tryCatchPattern":"try { prql_compile(query); } catch (e) { if (e.message.includes(\"parameter `rows`\")) { /* convert arg to a range tuple */ } else { throw e; } }","preventionTips":["Always use (start..end) range syntax","Never pass a single number or a list for rows","Use rolling: for fixed-size frames instead"],"tags":["prql","window","range","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"e164e249b99485890036eb60f57c37520379b240","analyzedAt":"2026-09-09T12:18:38.727Z","contentChangedAt":"2026-09-09T12:18:38.727Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}