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

  1. Create a vector index on the table before running a streaming vector index lookup join, and ensure the query matches the index definition.
  2. 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)