databendlabs/databend · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

A `unreachable!()` panic in the mutation organize plan's `build_pipeline2`. The match over `MutationStrategy` handles reordering inputs, row-id resizing, and NotMatchedOnly, but asserts `Direct` never occurs here. Reaching it means a Direct-strategy mutation organize plan was built through an incompatible branch — an internal invariant breach in the physical planner.

Solutions

  1. File a Databend issue with the failing query plan, since Direct strategies should not reach this code path
  2. Upgrade Databend to a version where Direct strategy pipeline building is handled separately
  3. Verify the physical plan source: check which optimizer pass produced a MutationOrganize with Direct strategy
  4. Work around by restructuring the MERGE INTO so the planner emits a MatchedOnly/MixedMatched/NotMatchedOnly strategy

Example fix

// before
MutationStrategy::NotMatchedOnly => {}
MutationStrategy::Direct => unreachable!(),
// after
MutationStrategy::NotMatchedOnly | MutationStrategy::Direct => {} // Direct needs no input reorganization
Defensive patterns

Strategy: try-catch

Validate before calling

if matches!(organize_plan.strategy, MutationStrategy::Direct) {
    return Err(ErrorCode::Internal("Direct strategy reaches MutationOrganize builder"));
}

Type guard

fn needs_input_reorg(s: &MutationStrategy) -> bool { !matches!(s, MutationStrategy::Direct) }

Try / catch

std::panic::catch_unwind(AssertUnwindSafe(|| self.build_pipeline2(builder))).map_err(|_| ErrorCode::Internal("organize pipeline build panicked"))

Prevention

When it happens

Trigger: Building a pipeline for a MutationOrganize physical plan whose strategy field is `MutationStrategy::Direct`; the builder expects only MatchedOnly/MixedMatched/NotMatchedOnly strategies that need input reordering or row-id handling.

Common situations: MERGE INTO queries after optimizer changes where Direct strategy was introduced but MutationOrganize's builder was not updated; running plans produced by a mismatched planner/executor version combination.

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

Appendix: source

Thrown at src/query/service/src/physical_plans/physical_mutation_into_organize.rs:116

                for idx in 0..row_id_len {
                    rules.push(idx);
                    rules.push(idx + row_id_len);
                }
                builder.main_pipeline.reorder_inputs(rules);
                self.resize_row_id(2, builder)?;
            }
            MutationStrategy::MatchedOnly => {
                assert_eq!(builder.main_pipeline.output_len() % 2, 0);
                let row_id_len = builder.main_pipeline.output_len() / 2;
                for idx in 0..row_id_len {
                    rules.push(idx);
                    rules.push(idx + row_id_len);
                }
                builder.main_pipeline.reorder_inputs(rules);
                self.resize_row_id(2, builder)?;
            }
            MutationStrategy::NotMatchedOnly => {}
            MutationStrategy::Direct => unreachable!(),
        }
        Ok(())
    }
}

impl MutationOrganize {
    fn resize_row_id(&self, step: usize, builder: &mut PipelineBuilder) -> Result<()> {
        // resize row_id
        let row_id_len = builder.main_pipeline.output_len() / step;
        let mut ranges = Vec::with_capacity(builder.main_pipeline.output_len());
        let mut vec = Vec::with_capacity(row_id_len);
        for idx in 0..row_id_len {
            vec.push(idx);
        }
        ranges.push(vec.clone());

        // data ports
        for idx in 0..row_id_len {

View on GitHub (pinned to 288d84d76e)