PRQL/prql · error · Error
expected a type, found
Error message
expected a type, found {decl} What it means
When resolving a type expression (e.g. inside a function parameter's type annotation, `#` type position), PRQL resolves the identifier and requires the declaration to have a type (DeclKind::Ty). If the identifier names a function, column, or other non-type declaration, this error is thrown.
Solutions
- Use a valid type name from std (e.g. `int`, `text`, `date`, `bool`)
- Fix typos in the type annotation
- Ensure the identifier is not shadowed by a local function/variable of the same name
Example fix
// before func add x:intger -> x + 1 // after func add x:int -> x + 1
Defensive patterns
Strategy: validation
Validate before calling
const VALID_TYPES = ["int","float","bool","text","date","time","timestamp","column","table","relation","any"];
function validateTypeAnnotation(t) {
if (!VALID_TYPES.includes(t)) throw new Error(`unknown type annotation: ${t}`);
} Type guard
function isTypeName(id, knownTypes) {
return knownTypes.includes(id.name);
} Try / catch
try {
compile(query);
} catch (e) {
if (e.message.includes("expected a type, found")) {
console.error("Type annotation must name a std type; check spelling and shadowing:", e.message);
} else { throw e; }
} Prevention
- Use documented std type names in annotations
- Avoid naming variables/functions after types
- Upgrade-aware: check type renames between PRQL versions
When it happens
Trigger: Writing a type annotation that references a non-type declaration, e.g. `func f x:table -> ...` where `table` is not the type name expected, or annotating with a function/variable name by mistake.
Common situations: Typo in a type name (e.g. `text` vs `string` depending on std version), using a value name as a type, or importing shadowing a type name.
Related errors
- expected , found
- expected a value, found a type
- expected a table or query, found an empty array `[]`
- expected a table or query, found an empty tuple
- {}
AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09).
Data as JSON: /api/errors/3a31132b0d1a4324.
Report an issue: GitHub.
Appendix: source
Thrown at prqlc/prqlc/src/semantic/resolver/expr.rs:28
use crate::Result;
use crate::{Error, Reason, Span, WithErrorInfo};
impl pl::PlFold for Resolver<'_> {
fn fold_stmts(&mut self, _: Vec<pl::Stmt>) -> Result<Vec<pl::Stmt>> {
unreachable!()
}
fn fold_type(&mut self, ty: Ty) -> Result<Ty> {
Ok(match ty.kind {
TyKind::Ident(ident) => {
self.root_mod.module.shadow(NS_THIS);
self.root_mod.module.shadow(NS_THAT);
let fq_ident = self.resolve_ident(&ident)?;
let decl = self.root_mod.module.get(&fq_ident).unwrap();
let decl_ty = decl.kind.as_ty().ok_or_else(|| {
Error::new(Reason::Expected {
who: None,
expected: "a type".to_string(),
found: decl.to_string(),
})
})?;
let mut ty = decl_ty.clone();
ty.name = ty.name.or(Some(fq_ident.name));
self.root_mod.module.unshadow(NS_THIS);
self.root_mod.module.unshadow(NS_THAT);
ty
}
_ => pl::fold_type(self, ty)?,
})
}
fn fold_var_def(&mut self, var_def: pl::VarDef) -> Result<pl::VarDef> {View on GitHub (pinned to e164e249b9)