PRQL/prql · error · Error
input to append by:name must not have any unnamed columns
Error message
{name} input to append by:name must not have any unnamed columns What it means
For `append ... by:name`, every column in each input must have a name, since columns are matched by name. This error is raised when an input contains an unnamed column (e.g. an anonymous expression column produced without an alias), making by-name matching impossible.
Solutions
- Alias every expression column before the append, e.g. `select [total = amount * 1.1]`.
- Ensure aggregates are named: `aggregate [total = sum amount]`.
- Inspect each input with a `select` listing all named columns.
- Fall back to positional `append` if names are irrelevant.
Example fix
// before from t | select [amount * 1.1] | append other by:name // after from t | select [adjusted = amount * 1.1] | append other by:name
Defensive patterns
Strategy: validation
Validate before calling
// Ensure every select item in by:name pipelines has an alias
function allSelectItemsNamed(prql) {
const selects = prql.match(/select\s+\[([^\]]+)\]/g) || [];
for (const s of selects) {
for (const item of s.slice(s.indexOf('[') + 1, -1).split(',')) {
const t = item.trim();
if (t && !/^\w+$/.test(t) && !/\w\s*=/.test(t)) {
throw new Error(`unnamed column in select: ${t}; alias it as name = ${t}`);
}
}
}
} Type guard
function isNamedSelectItem(item) {
return /^\w+$/.test(item.trim()) || /^[\w.]+\s*=/.test(item.trim());
} Try / catch
try {
const sql = prqlc.compile(query);
} catch (e) {
if (e.message.includes('must not have any unnamed columns')) {
// flag the expression column and add an alias
} else throw e;
} Prevention
- Alias every computed column: `select [total = amount * 1.1]`.
- Name all aggregates: `aggregate [total = sum amount]`.
- Lint pipelines: no bare expressions in select before by:name appends.
When it happens
Trigger: Appending with `by:name` where an input pipeline contains an expression column without an alias, such as `select [count]` on an aggregate without naming, or `derive`/`select` of an expression that yields `LineageColumn::Single { name: None }`.
Common situations: Selecting raw expressions (e.g. `select [amount * 1.1]`) without an alias before a by-name append; unnamed aggregate outputs; columns from functions that don't assign names.
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
- input to append by:name must have all columns defined
- `by`: expected position or name, found
- ` `: expected relation, 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/3a479a4197863543.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:286
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 {
(TransformKind::Append(Box::new(bottom)), top)
}
}
"loop" => {
let [pipeline, tbl] = unpack::<2>(func.args);
let pipeline = self.fold_by_simulating_eval(pipeline, &tbl)?;
(TransformKind::Loop(Box::new(pipeline)), tbl)View on GitHub (pinned to e164e249b9)