databendlabs/databend · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

This `unreachable!()` in `VisitorCast::from_visitor` fires when a `downcast_mut::<T>()` on a boxed `PhysicalPlanVisitor` returns None — i.e., the visitor's concrete type does not match the type the cast target expects. The visitor system's invariant is that callers only downcast after a matching type check; a mismatched or unordered check/cast sequence breaks it.

Solutions

  1. Find the call site performing the unchecked downcast and add/repair the corresponding type check (check_physical_plan / as_any downcast check) before casting
  2. Ensure every new PhysicalPlan variant has a matching visitor arm so dispatch never routes the wrong visitor type here
  3. Run the physical-plan visitor tests after adding plan node types to catch dispatch mismatches
  4. If reproducible on a stock plan, file a Databend bug with the query and plan tree

Example fix

// before
let casted: &mut MyVisitor = from_visitor(boxed); // may unreachable!()
// after
if T::check_physical_plan(plan) {
    let casted: &mut MyVisitor = from_visitor(boxed);
} else {
    return Err(ErrorCode::Internal("unexpected visitor type"));
}
Defensive patterns

Strategy: validation

Validate before calling

// Always verify the concrete visitor type before casting
if !T::check_physical_plan(plan) {
    return Err(ErrorCode::Internal("visitor type mismatch"));
}

Type guard

fn visitor_is<T: PhysicalPlanVisitor + 'static>(x: &Box<dyn PhysicalPlanVisitor>) -> bool {
    x.as_any().is::<T>()
}

Try / catch

// Wrap traversal dispatch and fall back to the generic visitor on mismatch
std::panic::catch_unwind(AssertUnwindSafe(|| T::from_visitor(boxed).visit(plan)))
    .unwrap_or_else(|_| generic_visit(plan))

Prevention

When it happens

Trigger: Calling a typed visitor method on a `&mut Box<dyn PhysicalPlanVisitor>` without a preceding `check_physical_plan`/type check, or dispatching to the wrong visitor implementation so the downcast fails.

Common situations: Extending PhysicalPlan with a new node type or visitor and forgetting to keep the visitor dispatch and cast in sync; code refactors that reorder type checks and casts; hand-written visitor traversal code.

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/ca2af03505999703. Report an issue: GitHub.

Appendix: source

Thrown at src/query/service/src/physical_plans/physical_plan.rs:239

        )))
    }
}

pub trait PhysicalPlanVisitor: Send + Sync + 'static {
    fn as_any(&mut self) -> &mut dyn Any;

    fn visit(&mut self, plan: &PhysicalPlan) -> Result<()>;
}

pub trait VisitorCast {
    fn from_visitor(x: &mut Box<dyn PhysicalPlanVisitor>) -> &mut Self;
}

impl<T: PhysicalPlanVisitor> VisitorCast for T {
    fn from_visitor(x: &mut Box<dyn PhysicalPlanVisitor>) -> &mut T {
        match x.as_any().downcast_mut::<T>() {
            Some(x) => x,
            None => unreachable!(),
        }
    }
}

pub trait PhysicalPlanCast {
    fn check_physical_plan(plan: &PhysicalPlan) -> bool;

    fn from_physical_plan(plan: &PhysicalPlan) -> Option<&Self>;

    fn from_mut_physical_plan(plan: &mut PhysicalPlan) -> Option<&mut Self>;
}

impl<T: IPhysicalPlan> PhysicalPlanCast for T {
    fn check_physical_plan(plan: &PhysicalPlan) -> bool {
        plan.as_any().downcast_ref::<T>().is_some()
    }

    fn from_physical_plan(plan: &PhysicalPlan) -> Option<&T> {

View on GitHub (pinned to 288d84d76e)