databendlabs/databend · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

get_mutation_table_result builds a summary DataBlock for mutation results and maps each mutation plan kind (INSERT/UPDATE/DELETE) to a row-count column. Any plan name outside those three constants is treated as impossible and hits an `unreachable!()`, panicking with "internal error: entered unreachable code". It signals that a mutation plan variant reached result aggregation without a defined row-count mapping.

Solutions

  1. Check which mutation plan name reached get_mutation_table_result (add the name to the panic or log it).
  2. Add a match arm for the new plan kind that pushes its row-count column.
  3. Audit all creators of Mutation plan nodes to ensure their plan names are covered.
  4. Pin/query on a release where only INSERT/UPDATE/DELETE mutation plans exist if you hit this at runtime.

Example fix

// before
_ => unreachable!(),
// after
other => {
    columns.push(UInt64Type::from_data(vec![0]));
    tracing::warn!("unhandled mutation plan {} in mutation result", other);
}
Defensive patterns

Strategy: validation

Validate before calling

// Before executing a mutation, confirm its plan kind is one of the supported ones
assert!(matches!(plan_name.as_str(), "insert" | "update" | "delete"),
    "unsupported mutation plan: {}", plan_name);

Type guard

fn is_supported_mutation(name: &str) -> bool {
    matches!(name, plans::INSERT_NAME | plans::UPDATE_NAME | plans::DELETE_NAME)
}

Prevention

When it happens

Trigger: inject_result is called with a mutation status whose plan name is not one of plans::INSERT_NAME, plans::UPDATE_NAME, or plans::DELETE_NAME — i.e. a new Mutation/InsertPlan variant (e.g. a REPLACE or MERGE-like plan) is executed but was not registered in this match.

Common situations: Running a freshly added DML statement type on an engine build that still maps only the classic three mutation kinds; internal version skew after adding a new mutation plan without updating the result interpreter.

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

Appendix: source

Thrown at src/query/service/src/interpreters/interpreter_mutation.rs:225

            PhysicalPlanBuilder::new(mutation.metadata.clone(), self.ctx.clone(), dry_run);
        builder.set_mutation_build_info(mutation_build_info);
        builder
            .build(&self.s_expr, *mutation.required_columns.clone())
            .await
    }

    fn get_mutation_table_result(&self) -> Result<Vec<DataBlock>> {
        let binding = self.ctx.mutation_state().mutation_status();
        let status = binding.read().unwrap();
        let mut columns = Vec::new();
        for field in self.schema.as_ref().fields() {
            match field.name().as_str() {
                plans::INSERT_NAME => columns.push(UInt64Type::from_data(vec![status.insert_rows])),
                plans::UPDATE_NAME => columns.push(UInt64Type::from_data(vec![status.update_rows])),
                plans::DELETE_NAME => {
                    columns.push(UInt64Type::from_data(vec![status.deleted_rows]))
                }
                _ => unreachable!(),
            }
        }
        Ok(vec![DataBlock::new_from_columns(columns)])
    }
}

pub async fn build_mutation_info(
    ctx: Arc<QueryContext>,
    mutation: &Mutation,
    dry_run: bool,
    materialized_view_refresh_target: Option<u64>,
) -> Result<MutationBuildInfo> {
    let table = ctx
        .get_table(
            &mutation.catalog_name,
            &mutation.database_name,
            &mutation.table_name,
        )

View on GitHub (pinned to 288d84d76e)