PRQL/prql · error · Error
expected a pipeline that resolves to a table, found
Error message
expected a pipeline that resolves to a table, found `{found_str}` What it means
During lowering (semantic IR to SQL IR), PRQL expects the function-call argument or pipeline fed to a relational context (e.g. `from x | ...` used as a value) to resolve to a table. If the expression instead lowers to a non-table value (a scalar, column, or unlowered expression), the compiler throws this error and then tries to attach hints for common mistakes.
Solutions
- Ensure the expression is a full pipeline that ends in a table (e.g. `from employees`) rather than a scalar or column expression
- If you intended a scalar comparison, move the pipeline out of the scalar context or use `first`/aggregate to reduce it to a value
- Check the found expression in the error message; correct typos or missing `from` clauses
- See the attached hint (the compiler adds hints for common mistakes such as missing `from`)
Example fix
// before select (employees) // after from employees | select name
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the expression is a pipeline starting with from
// e.g. reject scalars/strings passed as sources
if (!query.trim().startsWith("from ")) {
throw new Error("pipeline must start with `from <table>`");
} Type guard
function isTablePipeline(expr) {
return typeof expr === "string" && /(^|\|)\s*from\s+\w+/.test(expr);
} Try / catch
try {
compile(query);
} catch (e) {
if (e.message.includes("a pipeline that resolves to a table")) {
console.error("Add a `from <table>` clause; subqueries need a full pipeline:", e.message);
} else { throw e; }
} Prevention
- Always start pipelines with `from <table>`
- Do not nest `from` pipelines in scalar contexts like select
- Use first/aggregate to reduce relations to values when a scalar is needed
When it happens
Trigger: Passing a non-table expression where a relation is required, e.g. `select (from employees)` (subquery in scalar position), `join`ing against a scalar, or feeding a column expression where a pipeline resolving to a table is expected.
Common situations: Writing an inline subquery without the std-style pattern, mistyping a table name so it resolves to something else, or using a scalar function result as a pipeline source.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- expected an identifier, 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/0b0c05d7bcc56a95.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/lowering.rs:431
log::debug!("lowering literal relation table, columns = {columns:?}");
let relation = rq::Relation {
kind: rq::RelationKind::Literal(lit),
columns,
};
self.table_buffer.push(TableDecl {
id: tid,
name: None,
relation,
});
// return an instance of this new table
self.create_a_table_instance(id, None, tid)
}
_ => {
let found_str = write_pl(expr.clone());
let mut error = Error::new(Reason::Expected {
who: None,
expected: "a pipeline that resolves to a table".to_string(),
found: format!("`{}`", found_str),
});
// Provide better hints for common mistakes
if found_str.starts_with("internal std.sub") {
// This is likely a negative number or expression that should be wrapped in parentheses
error = error.push_hint(
"wrap negative numbers in parentheses, e.g. `sort (-column_name)`",
);
} else {
error = error.push_hint("`from` statement might be missing?");
}
return Err(error.with_span(expr.span));
}
})View on GitHub (pinned to e164e249b9)