PRQL/prql · error · Error
`take`: expected early or late, found
Error message
`take`: expected early or late, found {ident} What it means
The `take`-related dedup argument accepts only the literal values `early` or `late`, which control whether uniqueness is enforced before or after the take. Any other value passed where `early`/`late` is expected is rejected with this error at resolve time.
Solutions
- Use exactly `"early"` or `"late"` as the take argument literal.
- Check spelling and case; the comparison is against `"early"`/`"late"` strings.
- Remove the argument if you intended default behavior rather than a custom value.
Example fix
// before uniq take: earyl // after uniq take: "early"
Defensive patterns
Strategy: validation
Validate before calling
const TAKE_MODES = ['"early"', '"late"'];
if (!TAKE_MODES.includes(mode)) throw new Error(`take mode must be "early" or "late", got ${mode}`); Type guard
const isTakeMode = (v) => v === '"early"' || v === '"late"';
Try / catch
try { compile(prql) } catch (e) { if (e.message.includes('`take`: expected early or late')) { /* fix literal */ } } Prevention
- Keep mode values in a constant enum limited to early/late
- Quote the literal in PRQL: `take: "early"`
- Watch for case and spelling; the check is exact-match on lowercase literals
When it happens
Trigger: Calling `std.tuple_uniq` (the `take` argument) with anything other than the string literals `"early"` or `"late"` — e.g. a misspelled value, a non-literal expression, a variable, or quoting mistakes like `'EarLY'`.
Common situations: Typo in the flag (`earyl`, `last`), passing a dynamic/computed value instead of a literal, or copy-pasting SQL `DISTINCT`-style options into PRQL.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- `format`: expected csv or json, found
- tuple: expected to have at least one entry when initial…
- std.from_text: expected a string literal, found
- Unexpected: assign to
- expected a table, found
AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09).
Data as JSON: /api/errors/3c89a12fb260feb4.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:442
return Ok(Expr::new(ExprKind::Tuple(res)));
}
"tuple_uniq" => {
let [take, list] = unpack::<2>(func.args);
let take_late = {
let span = take.span;
let ident = take.clone().try_cast(
ExprKind::into_literal,
Some("`take`"),
"early or late",
)?;
match ident.to_string().as_str() {
"\"early\"" => false,
"\"late\"" => true,
_ => {
return Err(Error::new(Reason::Expected {
who: Some("`take`".to_string()),
expected: "early or late".to_string(),
found: ident.to_string(),
})
.with_span(span))
}
}
};
let list_items = list.kind.into_tuple().unwrap();
log::trace!("tuple_uniq before: {list_items:#?}");
let mut list_names: Vec<String> = Vec::new();
let mut list_out: HashMap<String, Expr> = HashMap::new();
for item in list_items {
let Some(name) = (match (&item.alias, &item.kind) {View on GitHub (pinned to e164e249b9)