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

  1. Pass a literal list: `filter code in ['A', 'B', 'C']`.
  2. Use a range pattern for intervals: `filter age in 18..65`.
  3. Replace a subquery membership test with a join or `filter` over a `from` pipeline.
  4. 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

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


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)