PRQL/prql · error · Error
expected an identifier, found
Error message
expected an identifier, found {found} What it means
Lowering converts resolved semantic expressions into SQL IR, and some constructs (like `std.all` expansion results) can only be lowered when they end up as plain identifiers. If `find_selected_all` or the expr lowering match reaches any expression kind that is not an identifier where one is required, this error is thrown.
Solutions
- Replace the offending expression with a plain column identifier
- Expand the desired columns explicitly instead of relying on `all`/`except` for expression entries
- Simplify the `except` list to contain only column names
Example fix
// before
select { all(), except { count() } }
// after
select { all(), except { value } } # except only column names Defensive patterns
Strategy: validation
Validate before calling
// Restrict all/except to plain column identifiers
const isIdent = (s) => /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(s);
if (!except.every(isIdent)) throw new Error("except must list plain column names"); Type guard
function isPlainIdentifier(node) {
return node && node.kind === "ident";
} Try / catch
try {
compile(query);
} catch (e) {
if (e.message.includes("expected an identifier")) {
console.error("all/except selections must expand to identifiers; expand columns manually.");
} else { throw e; }
} Prevention
- Use only column names inside all/except lists
- Expand complex expressions manually instead of via `all`
- Test selection expansions on small schemas first
When it happens
Trigger: An `all` selection expansion (within/except) produces a non-identifier node that reaches the lowering path expecting a column name, e.g. complex expressions combined with `except` that do not reduce to identifiers.
Common situations: Using `all` / `except` with expressions like function calls or literals inside the selection, which cannot be named as columns in the output.
Related errors
- expected a pipeline that resolves to a table, found
- Unexpected ` ` (this is probably a 'bad type' error)
- {}
- Currently `lex` only works with a single source, but found…
- Currently `annotate` only works with a single source, but…
AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09).
Data as JSON: /api/errors/14213f9f2e1bbeec.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/lowering.rs:793
continue;
}
let id = e.target_id.unwrap();
match e.kind {
pl::ExprKind::Ident(_) if e.ty.as_ref().is_some_and(|x| x.kind.is_tuple()) => {
res.extend(self.find_selected_all(e, None).with_span(except.span)?);
}
pl::ExprKind::Ident(ident) => {
res.insert(
self.lookup_cid(id, Some(&ident.name))
.with_span(except.span)?,
);
}
pl::ExprKind::All { within, except } => {
res.extend(self.find_selected_all(*within, Some(*except))?)
}
_ => {
return Err(Error::new(Reason::Expected {
who: None,
expected: "an identifier".to_string(),
found: write_pl(e),
}));
}
}
}
Ok(res)
}
fn declare_as_column(
&mut self,
mut expr_ast: pl::Expr,
is_aggregation: bool,
) -> Result<rq::CId> {
// short-circuit if this node has already been lowered
if let Some(LoweredTarget::Compute(lowered)) = self.node_mapping.get(&expr_ast.id.unwrap())
{View on GitHub (pinned to e164e249b9)