risingwavelabs/risingwave · error

core predicate must exist

Error message

core predicate must exist

What it means

to_stream_asof_join stores an EqPredicate in the core and then immediately unwraps as_eq_predicate_ref() with expect("core predicate must exist"). If the predicate is not an EqPredicate representation, the ASOF join cannot extract its inequality condition and panics.

Source

Thrown at src/frontend/src/optimizer/plan_node/logical_join.rs:1531

    ) -> Result<StreamPlanRef> {
        use super::stream::prelude::*;

        if predicate.eq_keys().is_empty() {
            return Err(ErrorCode::InvalidInputSyntax(
                "AsOf join requires at least 1 equal condition".to_owned(),
            )
            .into());
        }

        let (left, right) = self.get_stream_input_for_hash_join(&predicate, ctx)?;
        let left_len = left.schema().len();
        let mut core = self.core.clone_with_inputs(left, right);
        core.on = generic::JoinOn::EqPredicate(predicate);

        let inequality_desc = Self::get_inequality_desc_from_predicate(
            core.on
                .as_eq_predicate_ref()
                .expect("core predicate must exist")
                .other_cond()
                .clone(),
            left_len,
        )?;

        Ok(StreamAsOfJoin::new(core, inequality_desc)?.into())
    }

    /// Convert the logical join to a Hash join.
    fn to_batch_hash_join(
        &self,
        logical_join: generic::Join<BatchPlanRef>,
        predicate: EqJoinPredicate,
    ) -> Result<BatchPlanRef> {
        use super::batch::prelude::*;

        let left_schema_len = logical_join.left.schema().len();
        let asof_desc = self

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure the asof join core is built with generic::JoinOn::EqPredicate before calling as_eq_predicate_ref
  2. Use as_condition_ref-based extraction that tolerates both representations
  3. Verify upstream rules preserve the EqPredicate form for ASOF joins
  4. Report as an optimizer regression with the MV definition

Example fix

// before
.expect("core predicate must exist")
// after
.ok_or_else(|| anyhow!("asof join core predicate missing"))?
Defensive patterns

Strategy: type-guard

Validate before calling

if core.on.as_eq_predicate_ref().is_none() { /* handle missing/other representation */ }

Type guard

fn eq_pred_of(on: &generic::JoinOn) -> Option<&EqJoinPredicate> { on.as_eq_predicate_ref() }

Prevention

When it happens

Trigger: to_stream conversion of an ASOF join whose `on` predicate was rewritten to something other than JoinOn::EqPredicate before the extraction step.

Common situations: Custom optimizer rules or refactors changing JoinOn representation for asof joins; planner-produced asof joins after representation changes.

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/af5834ce97ea58af. Report an issue: GitHub.