PRQL/prql · error · Error
input to append by:name must have all columns defined
Error message
{name} input to append by:name must have all columns defined What it means
PRQL's native `append ... by:name` needs every column of both inputs to be individually known. If an input's lineage contains a wildcard `All` column (columns not yet expanded, e.g. from `from tbl` without a `select`), the compiler cannot perform by-name matching and throws this error. A hint suggests adding a `select` earlier in the pipeline.
Solutions
- Add a `select [col1, col2, ...]` before `append ... by:name` on the input that has undefined columns.
- List all columns explicitly on both sides so names are known to the compiler.
- Use positional `append` (no `by:`) if exact column lists are impractical.
- Replace `select *`-style usage with an explicit column list.
Example fix
// before from employees | append managers by:name // after from employees | select [id, name] | append (from managers | select [id, name]) by:name
Defensive patterns
Strategy: validation
Validate before calling
// Require an explicit select before every by:name append
function requireSelectBeforeByName(prql) {
const idx = prql.search(/append\s+\S+\s+by:name/);
if (idx >= 0 && !/select\s+\[[^\]]+\]\s*\|\s*append/.test(prql)) {
throw new Error('add an explicit select [cols...] before append by:name');
}
} Type guard
function hasExplicitSelect(pipeline) {
return /\|\s*select\s+\[[^\]]+\]/.test(pipeline);
} Try / catch
try {
const sql = prqlc.compile(query);
} catch (e) {
if (e.message.includes('must have all columns defined')) {
// auto-insert a select of known columns before the offending input
} else throw e;
} Prevention
- Always list columns explicitly with `select` before `append by:name`.
- Avoid wildcard column sets when by-name matching is needed.
- Prefer positional `append` when column lists are unstable.
When it happens
Trigger: Running `from employees | append managers by:name` where either side still has a star/wildcard column set (no `select`), so the lineage contains a `LineageColumn::All` entry.
Common situations: Using `by:name` directly on raw `from table` inputs; forgetting to narrow columns before the append; assuming PRQL auto-expands `table.*` for by-name unions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ` `: expected relation, found
- input to append by:name must not have any unnamed columns
- `by`: expected position or name, found
- {}
- 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/a24923639f49f0fa.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:277
}
}
};
// 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()),
})
.with_span(rel.span)
})?;
lineage.columns.iter().try_for_each(|c| match c {
LineageColumn::All { .. } => Err(Error::new(Reason::Simple(format!(
"{name} input to append by:name must have all columns defined"
)))
.push_hint("try adding a select earlier in the pipeline")
.with_span(rel.span)),
LineageColumn::Single {
name: None,
target_name: None,
..
} => Err(Error::new(Reason::Simple(format!(
"{name} input to append by:name must not have any unnamed columns"
)))
.with_span(rel.span)),
_ => Ok(()),
})?;
}
return Ok(new_binop(bottom, &["std", "_append_by_name"], top));
} else {View on GitHub (pinned to e164e249b9)