PRQL/prql · error · Error
std.in: expected a pattern, found
Error message
std.in: expected a pattern, found {found} What it means
The `std.in` operator tests membership in a list of values, and its argument must be a list literal (pattern) such as `[1, 2, 3]` or a range. This error is thrown when the argument to `in` cannot be resolved into a valid pattern — for example a bare scalar, an arbitrary expression, or a malformed list.
Solutions
- Pass a literal list: `filter code in ['A', 'B', 'C']`.
- Use a range pattern for intervals: `filter age in 18..65`.
- Replace a subquery membership test with a join or `filter` over a `from` pipeline.
- Check that the argument isn't a typo'd scalar or unparenthesized expression.
Example fix
// before from t | filter code in codes_table // after from t | filter code in ['A', 'B', 'C']
Defensive patterns
Strategy: validation
Validate before calling
// Validate std.in arguments are list literals or ranges
function validateInArgs(prql) {
const re = /in\s+([^\s|)]+)\s*([|)]|$)/g;
let m;
while ((m = re.exec(prql))) {
const arg = m[1].trim();
if (!arg.startsWith('[') && !/^(\d+\.\.|-?\d+\.\.\d+)/.test(arg)) {
throw new Error(`std.in expects a list literal or range, found: ${arg}`);
}
}
} Type guard
function isValidInPattern(arg) {
return Array.isArray(arg) || (arg != null && typeof arg === 'object' && 'start' in arg && 'end' in arg);
} Try / catch
try {
const sql = prqlc.compile(query);
} catch (e) {
if (e.message.includes('std.in: expected a pattern')) {
// suggest in [a, b, c] or a range; rewrite subquery membership as a join
} else throw e;
} Prevention
- Always use bracketed literal lists with `in`: `in ['a','b']`.
- Use ranges for interval checks: `in 1..10`.
- Do not pass subqueries, columns, or bare expressions to `in`; use a join instead.
When it happens
Trigger: Writing `x | in (foo + 1)` or `filter std.in some_expr` where the second argument fails to fold into a list/range pattern; also passing a single non-list value or a variable that is not a list literal.
Common situations: Using SQL habits like `col IN (SELECT ...)` expecting subquery support in PRQL `in`; passing a column or function call instead of a literal list; forgetting brackets around the value list.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- {}
- Currently `lex` only works with a single source, but found…
- Currently `annotate` only works with a single source, but…
- Currently `highlight` only works with a single source, but…
- failed to compile
AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09).
Data as JSON: /api/errors/489eaf5587ec1884.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:336
let pattern = match try_restrict_range(pattern) {
Ok((start, end)) => {
let start = restrict_null_literal(start);
let end = restrict_null_literal(end);
let start = start.map(|s| new_binop(value.clone(), &["std", "gte"], s));
let end = end.map(|e| new_binop(value, &["std", "lte"], e));
let res = maybe_binop(start, &["std", "and"], end);
let res = res.unwrap_or_else(|| {
Expr::new(ExprKind::Literal(Literal::Boolean(true)))
});
return Ok(res);
}
Err(expr) => expr,
};
return Err(Error::new(Reason::Expected {
who: Some("std.in".to_string()),
expected: "a pattern".to_string(),
found: write_pl(pattern.clone()),
})
.with_span(pattern.span));
}
"tuple_reduce" => {
// yes, this is not a transform, but this is the most appropriate place for it
let [init, func, list] = unpack::<3>(func.args);
let list_items = list.kind.into_tuple().unwrap();
let num_items = list_items.len();
let mut list_iter = list_items.into_iter();
let mut res = init.clone();
if let ExprKind::Literal(Literal::String(init_val)) = &init.kind {View on GitHub (pinned to e164e249b9)