risingwavelabs/risingwave · error
streaming vector index lookup join must be proctime…
Error message
streaming vector index lookup join must be proctime temporal join
What it means
Raised in LogicalVectorSearchLookupJoin::to_stream when the temporal join is not an AS OF PROCTIME join. Streaming vector-index lookup joins are only defined against the current processing time; other temporal join variants (event-time AS OF) cannot use the lookup executor, so the plan is rejected.
Solutions
- Define the temporal join in the streaming vector index lookup as a process-time (NOW() AS OF) temporal join.
- Use the standard temporal join syntax with process time on the lookup side.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at src/frontend/src/optimizer/plan_node/logical_vector_search_lookup_join.rs:306 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/d4cc7742cc6431b1.
Report an issue: GitHub.
Appendix: source
Thrown at src/frontend/src/optimizer/plan_node/logical_vector_search_lookup_join.rs:306
.is_identity()
{
// TODO: support it
bail!(
"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,View on GitHub (pinned to 6469eb736d)