pola-rs/polars · critical

cross join filter holds no keys

Error message

cross join filter holds no keys

What it means

Internal Rust panic in polars-plan indicating that a cross join's filter was expected to hold join keys but the JoinType variant being mutated has no key slots. It fires when code calls the key-setting helper on a join type other than the variants that store left_on/right_on keys (e.g. Range). This is an invariant violation inside the query planner, not a user-input error.

Source

Thrown at crates/polars-plan/src/plans/options.rs:739

    /// On [`Self::CrossAndFilter`], which holds no keys, or on a length mismatch where the
    /// variant stores keys in pairs.
    pub fn set_keys(&mut self, left: Vec<ExprIR>, right: Vec<ExprIR>) {
        if let Some(on) = self.key_pairs_mut() {
            *on = left.into_iter().zip_eq(right).collect();
            return;
        }
        match self {
            #[cfg(feature = "iejoin")]
            Self::IEJoin {
                left_on, right_on, ..
            }
            | Self::Range {
                left_on, right_on, ..
            } => {
                *left_on = left;
                *right_on = right;
            },
            _ => panic!("cross join filter holds no keys"),
        }
    }

    /// The match condition is exactly `left == right` for every key pair.
    ///
    /// True for [`Self::AsOf`] too: its strategy and tolerance live in [`JoinType::AsOf`],
    /// not in the match condition. False once a fused predicate is attached.
    pub fn is_pure_equi(&self) -> bool {
        !self.is_non_equi()
    }

    /// The match condition has a non-equality component.
    ///
    /// Use [`Self::key_pairs`] instead where what is needed is paired keys: a fused predicate
    /// join has those as well.
    pub fn is_non_equi(&self) -> bool {
        self.key_pairs().is_none() || self.has_fused_predicate()
    }

View on GitHub (pinned to 68506541d2)

Solutions

  1. If you are a polars contributor: handle the new/remaining JoinType variants explicitly instead of the wildcard _ arm
  2. Verify the JoinType is one that holds keys (Range/I Equi variants) before calling the setter
  3. If hit from Python, minimize the reproducing query and report it as a polars bug with the query plan
  4. Check you are on the latest polars release; planner panics are often fixed quickly

Example fix

// before
(join_type, keys) = match join_type { _ => panic!("cross join filter holds no keys") }
// after
match join_type {
    Self::Range { left_on, right_on, .. } => { *left_on = left; *right_on = right; },
    other => return Err(PolarsError::InvalidOperation("join type holds no keys".into())),
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Calling the internal key-assignment API (the method containing 'Self::Range { left_on, right_on, .. }' in crates/polars-plan/src/plans/options.rs:663) on a JoinType variant such as a cross join that carries no key columns; typically reached via programmatic construction or optimization passes that reassign join keys.

Common situations: Contributors modifying join planning code, adding a new JoinType variant, or optimizations that rewrite join keys on already-built join nodes. End users essentially never see this unless a higher-level API misroutes a join configuration into the planner.

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 pola-rs/polars@68506541d2 (2026-08-28). Data as JSON: /api/errors/a4a563439ccc31ef. Report an issue: GitHub.