risingwavelabs/risingwave · error
LogicalVectorSearchLookupJoin should use proper vector…
Error message
LogicalVectorSearchLookupJoin should use proper vector index in streaming job
What it means
Raised in LogicalVectorSearchLookupJoin::to_stream when no suitable vector index could be resolved for the streaming lookup. The executor requires a matching vector index on the lookup table (correct column types/distance function); without one the streaming plan cannot be built.
Solutions
- Create a vector index on the table before running a streaming vector index lookup join, and ensure the query matches the index definition.
- Verify the vector column and distance type match an existing index.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at src/frontend/src/optimizer/plan_node/logical_vector_search_lookup_join.rs:310 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/75bb347aae5c7e61.
Report an issue: GitHub.
Appendix: source
Thrown at src/frontend/src/optimizer/plan_node/logical_vector_search_lookup_join.rs:310
"LogicalVectorSearchLookupJoin does not support input that can possibly be rewritten"
)
}
Ok((
self.clone().into(),
ColIndexMapping::identity(self.base.schema().len()),
))
}
fn to_stream(&self, ctx: &mut ToStreamContext) -> Result<StreamPlanRef> {
if let Some(core) = self.to_vector_index_lookup_join(|plan| plan.to_stream(ctx))? {
// `ProcessTimeBroadcast` is intentionally excluded: the vector-index lookup executor
// does not consume a broadcast change stream or maintain replicated lookup state.
if !matches!(&core.as_of, Some(AsOf::ProcessTime)) {
bail!("streaming vector index lookup join must be proctime temporal join");
}
return Ok(StreamVectorIndexLookupJoin::new(core)?.into());
}
bail!("LogicalVectorSearchLookupJoin should use proper vector index in streaming job")
}
}
impl LogicalVectorSearchLookupJoin {
pub(crate) fn as_index_lookup(&self) -> Option<(&Arc<VectorIndex>, Vec<usize>, Option<AsOf>)> {
if let Some(scan) = self.core.lookup.as_logical_scan()
&& let Some((
index,
_covered_table_cols_idx,
non_covered_table_cols_idx,
primary_table_col_in_output,
)) = LogicalVectorSearch::resolve_vector_index_lookup(
scan,
&self.core.lookup_vector,
self.core.distance_type,
&self.core.lookup_output_indices,
)
&& non_covered_table_cols_idx.is_empty()View on GitHub (pinned to 6469eb736d)