{"record":{"id":"24e66a90d2cc3a57","repo":"databendlabs/databend","slug":"internal-error-entered-unreachable-code-24e66a","errorCode":null,"errorMessage":"internal error: entered unreachable code","messagePattern":"internal error: entered unreachable code","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs","lineNumber":96,"sourceCode":"                    return Ok(());\n                };\n                state.add_result(s_expr.replace_plan(Filter { predicates }));\n                Ok(())\n            }\n            1 => {\n                let scan = s_expr.plan.as_scan().unwrap();\n                let Some(predicates) = &scan.push_down_predicates else {\n                    return Ok(());\n                };\n                let Some(predicates) = RewritePredicates {}.rewrite(predicates)? else {\n                    return Ok(());\n                };\n                let mut scan = scan.clone();\n                scan.push_down_predicates = Some(predicates);\n                state.add_result(s_expr.replace_plan(scan));\n                Ok(())\n            }\n            _ => unreachable!(),\n        }\n    }\n\n    fn matchers(&self) -> &[Matcher] {\n        &self.matchers\n    }\n}\n\nimpl Default for RuleNormalizeScalarFilter {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nstruct RewritePredicates {}\n\nimpl RewritePredicates {\n    fn rewrite(&mut self, predicates: &[ScalarExpr]) -> Result<Option<Vec<ScalarExpr>>> {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs#L78-L114","documentation":"RuleNormalizeScalar's apply_matcher destructures the matched plan expecting only Scan or EvalScalar shapes; any other RelOperator reaching the arm panics with \"internal error: entered unreachable code\". The rule's matchers are supposed to guarantee the two supported shapes, so this panic marks a divergence between matcher declarations and the patterns handled in apply_matcher.","triggerScenarios":"A matcher (e.g. Operator::EvalScalar or Operator::Scan) matched an S-expression whose actual plan body is another operator variant — commonly after adding a new matcher without extending the match in apply_matcher.","commonSituations":"Hit during scalar normalization (predicate pushdown into scans) when planner rule sets change or when a new logical operator is introduced without updating this rule.","solutions":["Compare matchers() against every arm of the match in apply_matcher; extend the match to cover each declared matcher.","Reproduce with the failing query and dump the S-expression to identify the unmatched operator.","Replace `_ => unreachable!()` with `_ => Ok(())` / no-op so unmatched shapes are skipped instead of panicking.","Add a unit test asserting apply_matcher is total over the rule's declared matchers."],"exampleFix":"// before\n_ => unreachable!(),\n// after\n_ => Ok(()),","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Wrap query submission; on planner panic, simplify and retry\nlet res = exec(sql);\nif let Err(e) = &res, e.to_string().contains(\"internal error\") {\n    exec(simplify_predicates(sql));\n}","preventionTips":["Keep pushdown predicates (WHERE over scans/projections) in forms already supported by the rule.","After adding new matchers to a rule, audit the corresponding match arms.","Add regression tests covering every declared matcher.","Report new operator variants introduced by upgrades that bypass scalar normalization."],"tags":["rust","optimizer","panic","scalar"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}