PRQL/prql · error · Error
`by`: expected position or name, found
Error message
`by`: expected position or name, found {ident} What it means
This error comes from PRQL's `append` transform when used with the `by` option (e.g. `append other by:...`). The `by` argument must be exactly `position` or `name`; the resolver found some other identifier instead. It is thrown because PRQL's union-all-by-name/positional implementation only supports these two explicit modes.
Solutions
- Change the `by:` value to exactly `position` or `name` (lowercase).
- If you intended to match on a column, use `by:name` after ensuring both inputs have identically named columns (e.g. add a `select` to align column names).
- Check the PRQL version/docs: `append by:` only accepts these two keywords; positional matching is the default via plain `append other`.
Example fix
// before from t | append other by:colname // after from t | append other by:name
Defensive patterns
Strategy: validation
Validate before calling
// PRQL source check before compiling
const BY_KEYWORDS = new Set(["position", "name"]);
function validateAppendBy(prql) {
const m = prql.match(/by:\s*([\w"]+)/);
if (m && !BY_KEYWORDS.has(m[1].replaceAll('"', ''))) {
throw new Error(`append by: must be 'position' or 'name', got: ${m[1]}`);
}
} Type guard
function isValidByKeyword(v) {
return v === 'position' || v === 'name';
} Try / catch
try {
const sql = prqlc.compile(query);
} catch (e) {
if (e.message.includes('`by`: expected position or name')) {
// surface a fix hint: use by:position or by:name
} else throw e;
} Prevention
- Always use lowercase `by:position` or `by:name` verbatim.
- Do not pass column names to `by:`; align names with `select` instead.
- Add a unit test per pipeline using `append by:`.
When it happens
Trigger: Compiling a PRQL query like `from t | append other by:foo` where the identifier passed to `by:` is anything other than `position` or `name` (e.g. a misspelling like `by:name ` with an ident such as `by:Name`, `by:pos`, or a column name).
Common situations: Typo in `by:position`/`by:name`; passing a column name expecting `by:` to take a column; copying SQL `UNION ... BY NAME` syntax into PRQL without adapting it; confusion from older or newer PRQL syntax examples.
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
- ` `: expected relation, found
- input to append by:name must have all columns defined
- input to append by:name must not have any unnamed columns
- {}
- Currently `lex` only works with a single source, but found…
AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09).
Data as JSON: /api/errors/176c58117fbc6ee2.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:253
};
(transform_kind, tbl)
}
"append" => {
let [by, bottom, top] = unpack::<3>(func.args);
let by_name = {
let span = by.span;
let ident = by.clone().try_cast(
ExprKind::into_literal,
Some("`by`"),
"position or name",
)?;
match ident.to_string().as_str() {
"\"position\"" => false,
"\"name\"" => true,
_ => {
return Err(Error::new(Reason::Expected {
who: Some("`by`".to_string()),
expected: "position or name".to_string(),
found: ident.to_string(),
})
.with_span(span))
}
}
};
// TODO: support database engine-level UNION ALL BY NAME in PR #6037
if by_name {
// input validation for PRQL-native implementation
for (name, rel) in [("top", top.clone()), ("bottom", bottom.clone())] {
let lineage = rel.lineage.clone().ok_or_else(|| {
Error::new(Reason::Expected {
who: Some(format!("`{name}`")),
expected: "relation".to_string(),
found: write_pl(rel.clone()),View on GitHub (pinned to e164e249b9)