databendlabs/databend · error
plan in InsertInputSource::Stag must be CopyIntoTable
Error message
plan in InsertInputSource::Stag must be CopyIntoTable
What it means
connect_input_source in the REPLACE interpreter handles each InsertInputSource variant. When the source is InsertInputSource::Stage (with the storage-stage feature enabled), the embedded plan must specifically be a CopyIntoTable physical plan; any other plan type there violates the invariant and panics via unreachable!.
Solutions
- Inspect the REPLACE statement's stage source and confirm the planner emits CopyIntoTable for it.
- Upgrade to a build where the REPLACE planner produces CopyIntoTable for stage sources.
- Avoid REPLACE INTO ... FROM @stage; stage the data into a table first, then use REPLACE with a query source.
Example fix
// before
_ => unreachable!("plan in InsertInputSource::Stag must be CopyIntoTable"),
// after
other => Err(ErrorCode::Internal(format!(
"REPLACE stage source expects CopyIntoTable plan, got {:?}", other
))), Defensive patterns
Strategy: validation
Validate before calling
// Ensure REPLACE uses a query source, not a stage/stream source
let src = match &insert_plan.input_source {
InsertInputSource::SelectPlan(_) => Ok(()),
_ => Err("REPLACE only supports SELECT sources here"),
}; Prevention
- Don't combine REPLACE with stage COPY or streaming sources
- Test REPLACE statements against the planner output in CI
- Stage data into a table first, then REPLACE from that table
When it happens
Trigger: Executing REPLACE ... with a stage-based input source where the physical plan stored in InsertInputSource::Stage is not CopyIntoTable — e.g. the planner produced a different stage-read plan for REPLACE.
Common situations: Building Databend with the 'storage-stage' feature and issuing REPLACE INTO ... FROM @stage; planner changes that wrap or alter the stage COPY plan before REPLACE execution.
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
- internal error: entered unreachable code
- unexpected InternalColumnType in stage file reader
- stage_prefix should never be called on external stage, must…
- internal error: entered unreachable code
- internal error: entered unreachable code
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/8e7bf4884e784f8e.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/interpreters/interpreter_replace.rs:444
let (physical_plan, _, _) = interpreter
.build_physical_plan(_table_info, ©_plan, _table_meta_timestamps)
.await?;
// TODO optimization: if copy_plan.stage_table_info.files_to_copy is None, there should be a short-cut plan
*_purge_info = Some((
copy_plan.stage_table_info.files_to_copy.unwrap_or_default(),
copy_plan.stage_table_info.stage_info.clone(),
copy_plan.stage_table_info.copy_into_table_options.clone(),
));
Ok(ReplaceSourceCtx {
root: physical_plan,
select_ctx: None,
update_stream_meta: vec![],
bind_context: None,
})
}
_ => unreachable!("plan in InsertInputSource::Stag must be CopyIntoTable"),
},
#[cfg(not(feature = "storage-stage"))]
InsertInputSource::Stage(_) => Err(ErrorCode::Unimplemented(
"Stage COPY source support is disabled, rebuild with cargo feature 'storage-stage'",
)),
InsertInputSource::StreamingLoad { .. } => {
unreachable!("replace with streaming not supported yet")
}
}
}
fn connect_value_source(
&self,
schema: DataSchemaRef,
source: &InsertValue,
) -> Result<PhysicalPlan> {
Ok(PhysicalPlan::new(ReplaceAsyncSourcer {
schema,View on GitHub (pinned to 288d84d76e)