{"record":{"id":"34c7ecabbdae87db","repo":"PRQL/prql","slug":"expected-expected-str-found-found-str","errorCode":null,"errorMessage":"Expected {expected_str}, found {found_str}","messagePattern":"Expected (.+?), found (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"prqlc/prqlc-parser/src/parser/perror.rs","lineNumber":67,"sourceCode":"            };\n\n            if expected_strs.is_empty() || expected_strs.len() > 10 {\n                Error::new_simple(format!(\"unexpected {found_str}\"))\n            } else {\n                let mut expected_strs = expected_strs;\n                expected_strs.sort();\n\n                let expected_str = match expected_strs.len() {\n                    1 => expected_strs[0].clone(),\n                    2 => expected_strs.join(\" or \"),\n                    _ => {\n                        let last = expected_strs.pop().unwrap();\n                        format!(\"one of {} or {last}\", expected_strs.join(\", \"))\n                    }\n                };\n\n                match found {\n                    Some(_) => Error::new(Reason::Expected {\n                        who: None,\n                        expected: expected_str,\n                        found: found_str,\n                    }),\n                    None => Error::new(Reason::Simple(format!(\n                        \"Expected {expected_str}, but didn't find anything before the end.\"\n                    ))),\n                }\n            }\n        }\n        RichReason::Custom(msg) => Error::new_simple(msg.to_string()),\n    };\n\n    error.with_span(Some(span))\n}\n\nimpl<'a> From<Rich<'a, crate::lexer::lr::Token, Span>> for Error {\n    fn from(rich: Rich<'a, crate::lexer::lr::Token, Span>) -> Error {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/PRQL/prql/blob/e164e249b99485890036eb60f57c37520379b240/prqlc/prqlc-parser/src/parser/perror.rs#L49-L85","documentation":"The parser converts a `RichReason::Expected` into `Reason::Expected` when a construct was expected but something else was found. The message reads `Expected X, found Y` (with `one of a, b or c` when multiple tokens/keywords were acceptable).","triggerScenarios":"Structurally invalid query where a token/keyword was required: e.g. missing `|` between transforms, wrong keyword in a transform position, malformed function-call syntax passed to `prqlc compile`.","commonSituations":"Mixing SQL keyword order into PRQL, forgetting pipe characters, writing `sort`/`take` variants that don't exist, editing a valid query into an invalid one.","solutions":["Read the `Expected ... found ...` span and insert/replace the required token","Compare with a working PRQL example in the book","Run `prqlc fmt` on smaller chunks to isolate the malformed segment"],"exampleFix":"// before\nfrom employees filter age > 30\n// after\nfrom employees | filter age > 30","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { compile(prql) } catch (e) { if (e.reason === 'Expected') { hint(e.expected, e.span) } else { throw e } }","preventionTips":["Insert pipe separators between transforms","Cross-check keyword names against the PRQL book","Validate incrementally: compile after each transform is added"],"tags":["parser","syntax-error","parsing"],"backgroundTag":"invalid-argument-format","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"}