risingwavelabs/risingwave · error · BatchError

unspecified AsOf join inequality type

Error message

unspecified AsOf join inequality type

What it means

When deserializing an AsOf join inequality descriptor from its protobuf representation, the `inequality_type` field was `AsOfInequalityTypeUnspecified`. RisingWave requires an explicit inequality (Lt, Le, Gt, or Ge) to perform an ASOF join, so the batch executor builder rejects the plan instead of guessing. This is a plan-serialization/validation failure, not a runtime data issue.

Source

Thrown at src/batch/executors/src/executor/join/mod.rs:117

    Gt,
}

#[derive(Clone, Debug)]
pub struct AsOfDesc {
    pub left_idx: usize,
    pub right_idx: usize,
    pub inequality_type: AsOfInequalityType,
}

impl AsOfDesc {
    pub fn from_protobuf(desc_proto: &AsOfJoinDesc) -> crate::error::Result<Self> {
        let typ = match desc_proto.inequality_type() {
            AsOfJoinInequalityType::AsOfInequalityTypeLt => AsOfInequalityType::Lt,
            AsOfJoinInequalityType::AsOfInequalityTypeLe => AsOfInequalityType::Le,
            AsOfJoinInequalityType::AsOfInequalityTypeGt => AsOfInequalityType::Gt,
            AsOfJoinInequalityType::AsOfInequalityTypeGe => AsOfInequalityType::Ge,
            AsOfJoinInequalityType::AsOfInequalityTypeUnspecified => {
                bail!("unspecified AsOf join inequality type")
            }
        };
        Ok(Self {
            left_idx: desc_proto.left_idx as usize,
            right_idx: desc_proto.right_idx as usize,
            inequality_type: typ,
        })
    }
}

/// The layout be like:
///
/// [ `left` chunk     |  `right` chunk     ]
///
/// # Arguments
///
/// * `left` Data chunk padded to the left half of result data chunk..
/// * `right` Data chunk padded to the right half of result data chunk.

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Upgrade all RisingWave nodes (frontend, meta, compute) to the same version so ASOF join descriptors always serialize inequality_type.
  2. Check the plan serialization path that produced the AsOfJoinDesc and ensure `set_inequality_type` is called with Lt/Le/Gt/Ge before sending.
  3. Regenerate/rebuild the protobuf code if a custom client constructs the plan, confirming the field is populated (proto3 does not send default values).

Example fix

// before (client building the descriptor)
let desc = pb::AsOfJoinDesc { left_idx: 1, right_idx: 2, inequality_type: Default::default() };
// after
use pb::AsOfJoinInequalityType;
let desc = pb::AsOfJoinDesc { left_idx: 1, right_idx: 2, inequality_type: AsOfJoinInequalityType::AsOfInequalityTypeLe as i32 };
Defensive patterns

Strategy: validation

Validate before calling

// before submitting the plan, verify the descriptor is fully populated
fn validate_asof_desc(desc: &pb::AsOfJoinDesc) -> Result<()> {
    let t = AsOfJoinInequalityType::try_from(desc.inequality_type)
        .map_err(|_| anyhow!("asof join inequality_type must be set (Lt/Le/Gt/Ge)"))?;
    ensure!(t != AsOfJoinInequalityType::AsOfInequalityTypeUnspecified, "inequality_type unspecified");
    Ok(())
}

Prevention

When it happens

Trigger: Calling `AsOfJoinDesc::from_protobuf` (via building a batch executor from a plan fragment) where the protobuf `AsOfJoinDesc` message has `inequality_type` left at the default proto3 `Unspecified` value — e.g. the meta/frontend produced or an older binary sent a descriptor without setting the field.

Common situations: Version skew between frontend/meta and compute nodes where one side serializes ASOF joins without the inequality_type field; hand-crafted or fuzzed protobuf plan fragments; proto3 default-value omission when a client builds the plan programmatically.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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