risingwavelabs/risingwave · error · BatchError
VectorIndexNearest should have an input executor!
Error message
VectorIndexNearest should have an input executor!
What it means
VectorIndexNearestExecutorBuilder requires exactly one input executor. The nearest-neighbor lookup over a vector index consumes the candidate rows produced by an upstream executor (e.g. a scan), so the builder asserts inputs.len() == 1. Zero or multiple inputs indicate a malformed plan.
Source
Thrown at src/batch/executors/src/executor/vector_index_nearest.rs:49
pub struct VectorIndexNearestExecutor<S: StateStore> {
identity: String,
schema: Schema,
input: BoxedExecutor,
query_epoch: BatchQueryEpoch,
vector_column_idx: usize,
reader: VectorIndexReader<S>,
}
pub struct VectorIndexNearestExecutorBuilder {}
impl BoxedExecutorBuilder for VectorIndexNearestExecutorBuilder {
async fn new_boxed_executor(
source: &ExecutorBuilder<'_>,
inputs: Vec<BoxedExecutor>,
) -> Result<BoxedExecutor> {
ensure!(
inputs.len() == 1,
"VectorIndexNearest should have an input executor!"
);
let [input]: [_; 1] = inputs.try_into().unwrap();
let vector_index_nearest_node = try_match_expand!(
source.plan_node().get_node_body().unwrap(),
NodeBody::VectorIndexNearest
)?;
dispatch_state_store!(source.context().state_store(), state_store, {
let reader = VectorIndexReader::new(
vector_index_nearest_node.reader_desc.as_ref().unwrap(),
state_store,
);
let mut schema = input.schema().clone();
schema.fields.push(Field::new(
"vector_info",View on GitHub (pinned to 6469eb736d)
Solutions
- Verify the plan: VectorIndexNearest must have exactly one child executor; fix the planner that built the node.
- Ensure the required scan/source executor is attached as the single input of the node.
- When constructing this executor manually, supply exactly one input in the inputs vector.
- File an internal bug with the query if the plan looks correct.
Example fix
// before (missing input) BatchPlanNode::new(NodeBody::VectorIndexNearest(node), vec![]) // after (exactly one child) BatchPlanNode::new(NodeBody::VectorIndexNearest(node), vec![scan_executor])
Defensive patterns
Strategy: validation
Validate before calling
// Rust: exactly one input required
fn has_single_input(inputs: &[BoxedExecutor]) -> bool { inputs.len() == 1 } Type guard
fn single_input(inputs: Vec<BoxedExecutor>) -> Option<BoxedExecutor> {
let [input]: [_; 1] = inputs.try_into().ok()?;
Some(input)
} Try / catch
match builder.new_boxed_executor(&src, inputs).await {
Err(e) if e.to_string().contains("VectorIndexNearest should have an input") => {
// re-plan ensuring the scan child is attached
}
other => other,
} Prevention
- Always attach exactly one scan/source child to VectorIndexNearest plan nodes.
- Add planner tests for vector-index queries.
- Validate arity in tests when changing the vector-index plan-node shape.
When it happens
Trigger: new_boxed_executor is called where inputs.len() != 1 for a VectorIndexNearest plan node — typically zero children because the planner did not attach the source scan, or more than one child.
Common situations: Planner bugs when planning vector-index queries (missing the required scan child or attaching extra children); hand-built plan trees with wrong arity; version changes in the vector-index plan-node shape.
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
- Row sequential scan should not have input executor!
- Source should not have input executor!
- Row sequential scan should not have input executor!
- ValuesExecutor should have no child!
- GenerateSeriesExecutor should not have child!
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/bc83e925fd32398d.
Report an issue: GitHub.