{"record":{"id":"3a31132b0d1a4324","repo":"PRQL/prql","slug":"expected-a-type-found-decl","errorCode":null,"errorMessage":"expected a type, found {decl}","messagePattern":"expected a type, found (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"prqlc/prqlc/src/semantic/resolver/expr.rs","lineNumber":28,"sourceCode":"use crate::Result;\nuse crate::{Error, Reason, Span, WithErrorInfo};\n\nimpl pl::PlFold for Resolver<'_> {\n    fn fold_stmts(&mut self, _: Vec<pl::Stmt>) -> Result<Vec<pl::Stmt>> {\n        unreachable!()\n    }\n\n    fn fold_type(&mut self, ty: Ty) -> Result<Ty> {\n        Ok(match ty.kind {\n            TyKind::Ident(ident) => {\n                self.root_mod.module.shadow(NS_THIS);\n                self.root_mod.module.shadow(NS_THAT);\n\n                let fq_ident = self.resolve_ident(&ident)?;\n\n                let decl = self.root_mod.module.get(&fq_ident).unwrap();\n                let decl_ty = decl.kind.as_ty().ok_or_else(|| {\n                    Error::new(Reason::Expected {\n                        who: None,\n                        expected: \"a type\".to_string(),\n                        found: decl.to_string(),\n                    })\n                })?;\n                let mut ty = decl_ty.clone();\n                ty.name = ty.name.or(Some(fq_ident.name));\n\n                self.root_mod.module.unshadow(NS_THIS);\n                self.root_mod.module.unshadow(NS_THAT);\n\n                ty\n            }\n            _ => pl::fold_type(self, ty)?,\n        })\n    }\n\n    fn fold_var_def(&mut self, var_def: pl::VarDef) -> Result<pl::VarDef> {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/PRQL/prql/blob/e164e249b99485890036eb60f57c37520379b240/prqlc/prqlc/src/semantic/resolver/expr.rs#L10-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfunc add x:intger -> x + 1\n// after\nfunc add x:int -> x + 1","handlingStrategy":"validation","validationCode":"const VALID_TYPES = [\"int\",\"float\",\"bool\",\"text\",\"date\",\"time\",\"timestamp\",\"column\",\"table\",\"relation\",\"any\"];\nfunction validateTypeAnnotation(t) {\n  if (!VALID_TYPES.includes(t)) throw new Error(`unknown type annotation: ${t}`);\n}","typeGuard":"function isTypeName(id, knownTypes) {\n  return knownTypes.includes(id.name);\n}","tryCatchPattern":"try {\n  compile(query);\n} catch (e) {\n  if (e.message.includes(\"expected a type, found\")) {\n    console.error(\"Type annotation must name a std type; check spelling and shadowing:\", e.message);\n  } else { throw e; }\n}","preventionTips":["Use documented std type names in annotations","Avoid naming variables/functions after types","Upgrade-aware: check type renames between PRQL versions"],"tags":["prql","resolver","types"],"backgroundTag":"invalid-identifier","analyzedSha":"e164e249b99485890036eb60f57c37520379b240","analyzedAt":"2026-09-09T12:18:38.727Z","contentChangedAt":"2026-09-09T12:18:38.727Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}