databendlabs/databend · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

interpreter_insert's execute2 (src/query/service/src/interpreters/interpreter_insert.rs:474) matches on InsertInputSource and panics via unreachable!() for InsertInputSource::Stage. INSERT from a stage is supposed to be rewritten into an INSERT ... SELECT (a query source) before reaching this interpreter; a Stage source surviving to execute2 means an upstream rewrite was skipped or a new path bypassed it.

Solutions

  1. Rewrite the statement as `INSERT INTO t (SELECT ... FROM @stage ...)` or use `COPY INTO t FROM @stage`, which are the supported paths
  2. Upgrade to a Databend version where stage-source inserts are always rewritten to query sources or rejected with a clear user error
  3. Capture the exact SQL and version and file a bug — a Stage source must never reach execute2
  4. As a code fix, replace unreachable! with Err(ErrorCode::Internal("InsertInputSource::Stage should be rewritten to a query source"))

Example fix

-- before (panics)
INSERT INTO t FROM @my_stage;
-- after
INSERT INTO t (SELECT $1, $2 FROM @my_stage);
Defensive patterns

Strategy: validation

Validate before calling

-- never INSERT directly FROM @stage; use a SELECT or COPY INTO
INSERT INTO t (SELECT $1, $2 FROM @my_stage);
-- or: COPY INTO t FROM @my_stage;

Type guard

if matches!(plan.source, InsertInputSource::Stage(_)) {
    return Err(ErrorCode::BadArguments("rewrite stage-source INSERT as INSERT ... SELECT".into()));
}

Prevention

When it happens

Trigger: Executing `INSERT INTO t FROM @stage` (or equivalent direct stage-source insert) on a code path where the Stage source is not converted to a SELECT-based insert before execute2 runs.

Common situations: Users issuing INSERT directly from a stage instead of the supported COPY INTO or INSERT INTO ... SELECT FROM @stage forms; internal regressions where the stage-to-query rewrite was bypassed (e.g. via prepared plans or internal tooling).

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

Appendix: source

Thrown at src/query/service/src/interpreters/interpreter_insert.rs:474

            self.ctx
                .get_table_meta_timestamps(table.as_ref(), snapshot)?
        } else {
            // For non-fuse table, the table meta timestamps does not matter,
            // just passes a placeholder value here
            TableMetaTimestamps::new(None, Duration::hours(1))
        };

        let hook_lock_opt = if self.materialized_view_refresh_target.is_some() {
            // Materialized-view refresh holds its lifecycle lock across this pipeline.
            LockTableOption::NoLock
        } else {
            LockTableOption::LockNoRetry
        };
        let mut build_res = PipelineBuildResult::create();

        match &self.plan.source {
            InsertInputSource::Stage(_) => {
                unreachable!()
            }
            InsertInputSource::Values(InsertValue::Values { rows }) => {
                // Fixed-bucket PK Paimon tables need route + GlobalHash Exchange; unify with
                // the SELECT insert physical plan so single-node uses local channel repartition.
                if is_fixed_bucket_primary_key(&table)? {
                    let insert_schema = self.plan.dest_schema();
                    let (values_plan, bindings) =
                        values_to_constant_scan(rows, insert_schema.clone())?;
                    let select_schema = values_plan.output_schema()?;
                    let mut insert_plan = build_insert_select_physical_plan(
                        values_plan,
                        select_schema,
                        bindings,
                        insert_schema,
                        table.clone(),
                        false,
                        false,
                        table_meta_timestamps,

View on GitHub (pinned to 288d84d76e)