databendlabs/databend · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

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.

Solutions

  1. Compare matchers() against every arm of the match in apply_matcher; extend the match to cover each declared matcher.
  2. Reproduce with the failing query and dump the S-expression to identify the unmatched operator.
  3. Replace `_ => unreachable!()` with `_ => Ok(())` / no-op so unmatched shapes are skipped instead of panicking.
  4. Add a unit test asserting apply_matcher is total over the rule's declared matchers.

Example fix

// before
_ => unreachable!(),
// after
_ => Ok(()),
Defensive patterns

Strategy: try-catch

Try / catch

// Wrap query submission; on planner panic, simplify and retry
let res = exec(sql);
if let Err(e) = &res, e.to_string().contains("internal error") {
    exec(simplify_predicates(sql));
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/24e66a90d2cc3a57. Report an issue: GitHub.

Appendix: source

Thrown at src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs:96

                    return Ok(());
                };
                state.add_result(s_expr.replace_plan(Filter { predicates }));
                Ok(())
            }
            1 => {
                let scan = s_expr.plan.as_scan().unwrap();
                let Some(predicates) = &scan.push_down_predicates else {
                    return Ok(());
                };
                let Some(predicates) = RewritePredicates {}.rewrite(predicates)? else {
                    return Ok(());
                };
                let mut scan = scan.clone();
                scan.push_down_predicates = Some(predicates);
                state.add_result(s_expr.replace_plan(scan));
                Ok(())
            }
            _ => unreachable!(),
        }
    }

    fn matchers(&self) -> &[Matcher] {
        &self.matchers
    }
}

impl Default for RuleNormalizeScalarFilter {
    fn default() -> Self {
        Self::new()
    }
}

struct RewritePredicates {}

impl RewritePredicates {
    fn rewrite(&mut self, predicates: &[ScalarExpr]) -> Result<Option<Vec<ScalarExpr>>> {

View on GitHub (pinned to 288d84d76e)