{"record":{"id":"856a4d1667f65c6a","repo":"PRQL/prql","slug":"expected-expected-found-found","errorCode":null,"errorMessage":"expected {expected}, found `{found}`","messagePattern":"expected (.+?), found `(.+?)`","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"prqlc/prqlc/src/semantic/mod.rs","lineNumber":142,"sourceCode":"\n    pub(crate) fn name(&self) -> &str {\n        match &self.kind {\n            StmtKind::QueryDef(_) => NS_QUERY_DEF,\n            StmtKind::VarDef(VarDef { name, .. }) => name,\n            StmtKind::TypeDef(TypeDef { name, .. }) => name,\n            StmtKind::ModuleDef(ModuleDef { name, .. }) => name,\n            StmtKind::ImportDef(ImportDef { name, alias }) => alias.as_ref().unwrap_or(&name.name),\n        }\n    }\n}\n\nimpl pl::Expr {\n    fn try_cast<T, F, S2: ToString>(self, f: F, who: Option<&str>, expected: S2) -> Result<T, Error>\n    where\n        F: FnOnce(pl::ExprKind) -> Result<T, pl::ExprKind>,\n    {\n        f(self.kind).map_err(|i| {\n            Error::new(Reason::Expected {\n                who: who.map(|s| s.to_string()),\n                expected: expected.to_string(),\n                found: format!(\"`{}`\", write_pl(pl::Expr::new(i))),\n            })\n            .with_span(self.span)\n        })\n    }\n}\n\n/// Write a PL IR to string.\n///\n/// Because PL needs to be restricted back to AST, ownerships of expr is required.\npub fn write_pl(expr: pl::Expr) -> String {\n    let expr = ast_expand::restrict_expr(expr);\n\n    crate::codegen::write_expr(&expr)\n}\n#[cfg(test)]","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/PRQL/prql/blob/e164e249b99485890036eb60f57c37520379b240/prqlc/prqlc/src/semantic/mod.rs#L124-L160","documentation":"`pl::Expr::try_cast` is a helper in the semantic module: callers pass a closure that attempts to destructure an expression kind, and if it does not match, the error reports who/what was expected and the actual found expression. It is the generic 'wrong expression shape' error reused across the resolver and lowering for casts like 'expected a string literal'.","triggerScenarios":"Any resolver code path calling `try_cast` with an expression that does not match the required kind, e.g. passing a non-literal where a literal is required (`interval` arguments, sstring parts, named args, etc.).","commonSituations":"Using a variable instead of a literal where PRQL requires a constant (e.g. `date`/`interval` components), or writing `\"x\"` where a number is expected and similar.","solutions":["Read the `expected` field in the message and supply an expression of that shape","Replace non-literal values with literal ones where the language requires literals","Check the function signature in std declarations for the expected argument type"],"exampleFix":"// before\ninterval 1_day_part  # wrong shape\n// after\ninterval 1 day","handlingStrategy":"type-guard","validationCode":"// Validate literal-ness before calling APIs that require literals\nfunction requireLiteral(value, kind) {\n  if (typeof value !== kind.expectedJsType) {\n    throw new Error(`expected ${kind.name} literal, got ${typeof value}`);\n  }\n}","typeGuard":"function isStringLiteral(expr) {\n  return expr && expr.kind === \"literal\" && typeof expr.value === \"string\";\n}","tryCatchPattern":"try {\n  compile(query);\n} catch (e) {\n  if (/^expected .+, found/.test(e.message)) {\n    console.error(\"Expression shape mismatch — supply the literal/kind named in `expected`:\", e.message);\n  } else { throw e; }\n}","preventionTips":["Read the `expected` field of the message and match it","Use literals where PRQL requires constants (interval/date components)","Consult std function signatures for required argument kinds"],"tags":["prql","resolver","expr-cast"],"backgroundTag":"type-mismatch","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"}