{"record":{"id":"2ecb7cc5001f00ab","repo":"risingwavelabs/risingwave","slug":"watermark-serde-should-have-at-least-one-order-typ","errorCode":null,"errorMessage":"Watermark serde should have at least one order type","messagePattern":"Watermark serde should have at least one order type","errorType":"exception","errorClass":"StreamExecutorError","httpStatus":null,"severity":"error","filePath":"src/stream/src/common/table/state_table.rs","lineNumber":2206,"sourceCode":"                .await\n                .map(|s| s.boxed());\n        };\n        let watermark_row = watermark_serde.deserialize(&watermark_bytes)?;\n        if watermark_row.len() != 1 {\n            return Err(StreamExecutorError::from(format!(\n                \"Watermark row should have exactly 1 column, got {}\",\n                watermark_row.len()\n            )));\n        }\n        let watermark_value = watermark_row[0].clone();\n        // StateTableInner::update_watermark should ensure that the watermark is not NULL\n        if watermark_value.is_none() {\n            return Err(StreamExecutorError::from(anyhow!(\n                \"Watermark cannot be NULL\"\n            )));\n        }\n        let order_type = watermark_serde.get_order_types().get(0).ok_or_else(|| {\n            StreamExecutorError::from(anyhow!(\n                \"Watermark serde should have at least one order type\"\n            ))\n        })?;\n\n        let direction = if order_type.is_ascending() {\n            WatermarkDirection::Ascending\n        } else {\n            WatermarkDirection::Descending\n        };\n        let clean_watermark_index_in_pk = self\n            .pk_indices\n            .iter()\n            .position(|&i| i == clean_watermark_index);\n        let clean_watermark_index_in_value = match &self.value_indices {\n            Some(value_indices) => value_indices\n                .iter()\n                .position(|idx| *idx == clean_watermark_index)\n                .ok_or_else(|| {","sourceCodeStart":2188,"sourceCodeEnd":2224,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/common/table/state_table.rs#L2188-L2224","documentation":"After confirming the watermark value is non-NULL, the state table reads the watermark serde's order types to determine ascending/descending direction. This error fires when `watermark_serde.get_order_types()` returns an empty vector, meaning the serde was constructed without any ordering information, so the comparison direction cannot be computed.","triggerScenarios":"Calling the state table watermark update path with a WatermarkSerde built from an empty order-types slice — typically a serde misconstructed in executor/table initialization.","commonSituations":"Incorrect column list passed when building the serde during fragment/graph dispatch; a refactor or version change that dropped the order type from serde construction; malformed stream plan with no sort column on the watermark key.","solutions":["Inspect where the WatermarkSerde is constructed and ensure it is built with the watermark column's order type","Verify the stream plan fragment includes the sort/order type for the watermark column","Rebuild/upgrade to a version where serde construction matches the state table API","If persistent, log the full order_types vector at serde build time to confirm it is empty at creation"],"exampleFix":"// before\nlet serde = WatermarkSerde::new(vec![], data_types);\n// after\nlet serde = WatermarkSerde::new(vec![OrderType::Ascending], data_types);","handlingStrategy":"validation","validationCode":"fn check_serde(serde: &WatermarkSerde) -> Result<(), StreamExecutorError> {\n    if serde.get_order_types().is_empty() {\n        Err(StreamExecutorError::from(anyhow!(\"watermark serde has no order types\")))\n    } else { Ok(()) }\n}","typeGuard":"fn serde_has_order_type(serde: &WatermarkSerde) -> bool { !serde.get_order_types().is_empty() }","tryCatchPattern":null,"preventionTips":["Always construct WatermarkSerde with at least one OrderType","Assert serde construction in executor init with debug_assert!","Cover serde construction in unit tests for every watermark operator"],"tags":["rust","streaming","watermark","serde"],"backgroundTag":"empty-required-field","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"}