{"record":{"id":"cd6daa2cddda7486","repo":"risingwavelabs/risingwave","slug":"unspecified-asof-join-inequality-type","errorCode":null,"errorMessage":"unspecified AsOf join inequality type","messagePattern":"unspecified AsOf join inequality type","errorType":"validation","errorClass":"BatchError","httpStatus":null,"severity":"error","filePath":"src/batch/executors/src/executor/join/mod.rs","lineNumber":117,"sourceCode":"    Gt,\n}\n\n#[derive(Clone, Debug)]\npub struct AsOfDesc {\n    pub left_idx: usize,\n    pub right_idx: usize,\n    pub inequality_type: AsOfInequalityType,\n}\n\nimpl AsOfDesc {\n    pub fn from_protobuf(desc_proto: &AsOfJoinDesc) -> crate::error::Result<Self> {\n        let typ = match desc_proto.inequality_type() {\n            AsOfJoinInequalityType::AsOfInequalityTypeLt => AsOfInequalityType::Lt,\n            AsOfJoinInequalityType::AsOfInequalityTypeLe => AsOfInequalityType::Le,\n            AsOfJoinInequalityType::AsOfInequalityTypeGt => AsOfInequalityType::Gt,\n            AsOfJoinInequalityType::AsOfInequalityTypeGe => AsOfInequalityType::Ge,\n            AsOfJoinInequalityType::AsOfInequalityTypeUnspecified => {\n                bail!(\"unspecified AsOf join inequality type\")\n            }\n        };\n        Ok(Self {\n            left_idx: desc_proto.left_idx as usize,\n            right_idx: desc_proto.right_idx as usize,\n            inequality_type: typ,\n        })\n    }\n}\n\n/// The layout be like:\n///\n/// [ `left` chunk     |  `right` chunk     ]\n///\n/// # Arguments\n///\n/// * `left` Data chunk padded to the left half of result data chunk..\n/// * `right` Data chunk padded to the right half of result data chunk.","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/executors/src/executor/join/mod.rs#L99-L135","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Upgrade all RisingWave nodes (frontend, meta, compute) to the same version so ASOF join descriptors always serialize inequality_type.","Check the plan serialization path that produced the AsOfJoinDesc and ensure `set_inequality_type` is called with Lt/Le/Gt/Ge before sending.","Regenerate/rebuild the protobuf code if a custom client constructs the plan, confirming the field is populated (proto3 does not send default values)."],"exampleFix":"// before (client building the descriptor)\nlet desc = pb::AsOfJoinDesc { left_idx: 1, right_idx: 2, inequality_type: Default::default() };\n// after\nuse pb::AsOfJoinInequalityType;\nlet desc = pb::AsOfJoinDesc { left_idx: 1, right_idx: 2, inequality_type: AsOfJoinInequalityType::AsOfInequalityTypeLe as i32 };","handlingStrategy":"validation","validationCode":"// before submitting the plan, verify the descriptor is fully populated\nfn validate_asof_desc(desc: &pb::AsOfJoinDesc) -> Result<()> {\n    let t = AsOfJoinInequalityType::try_from(desc.inequality_type)\n        .map_err(|_| anyhow!(\"asof join inequality_type must be set (Lt/Le/Gt/Ge)\"))?;\n    ensure!(t != AsOfJoinInequalityType::AsOfInequalityTypeUnspecified, \"inequality_type unspecified\");\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep frontend, meta, and compute nodes on the same RisingWave version.","When constructing protobuf plans programmatically, always set every non-optional field explicitly; proto3 omits zero/default values.","Add a unit test that round-trips AsOfJoinDesc through protobuf for all four inequality types."],"tags":["batch-executor","protobuf","asof-join","plan-deserialization"],"backgroundTag":"invalid-enum-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}