{"record":{"id":"4b0e59f45bd265ee","repo":"risingwavelabs/risingwave","slug":"unexpected-node-body-for-stream-cdc-scan","errorCode":null,"errorMessage":"Unexpected node body for stream cdc scan","messagePattern":"Unexpected node body for stream cdc scan","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/rpc/ddl_controller.rs","lineNumber":1049,"sourceCode":"                    .await?\n                {\n                    found_cdc_scan = true;\n                }\n            }\n            // When there's generated columns, the cdc scan node is wrapped in a project node\n            Some(NodeBody::Project(_)) => {\n                for input in &stream_scan_fragment.nodes.input {\n                    assert_parallelism(stream_scan_fragment.distribution_type, &input.node_body);\n                    if self\n                        .validate_cdc_table_inner(&input.node_body, table.id)\n                        .await?\n                    {\n                        found_cdc_scan = true;\n                    }\n                }\n            }\n            _ => {\n                bail!(\"Unexpected node body for stream cdc scan\");\n            }\n        };\n        if !found_cdc_scan {\n            bail!(\"No stream cdc scan node found in stream scan fragment\");\n        }\n        Ok(())\n    }\n\n    async fn validate_cdc_table_inner(\n        &self,\n        node_body: &Option<NodeBody>,\n        table_id: TableId,\n    ) -> MetaResult<bool> {\n        if let Some(NodeBody::StreamCdcScan(stream_cdc_scan)) = node_body\n            && let Some(ref cdc_table_desc) = stream_cdc_scan.cdc_table_desc\n        {\n            let options_with_secret = WithOptionsSecResolved::new(\n                cdc_table_desc.connect_properties.clone(),","sourceCodeStart":1031,"sourceCodeEnd":1067,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/rpc/ddl_controller.rs#L1031-L1067","documentation":"validate_cdc_table inspects the generated stream fragments of a CDC table to confirm the scan fragment contains a StreamCdcScan node. If the StreamNode body is neither a fragment nor an expected node shape, the validation bails with 'Unexpected node body'. This is an internal shape check protecting against frontend/meta producing a plan the CDC validation cannot understand.","triggerScenarios":"Creating a CDC table whose generated stream scan fragment has a top-level node body variant other than the ones validate_cdc_table handles (e.g. after a plan/protobuf change or an unexpected ExternalStream/Source wrapper).","commonSituations":"Version skew between frontend and meta node after an upgrade; a new connector or node type added in the frontend but not yet handled in meta's CDC validation; hand-modified or corrupted fragment graphs.","solutions":["Check RisingWave component versions are consistent across frontend and meta; upgrade mismatched nodes together.","Inspect the generated fragment graph to see which node body type appeared; extend validate_cdc_table to handle it if it's a new legitimate node type.","Report to RisingWave maintainers if a standard CDC table creation triggers this — it indicates an internal invariant break."],"exampleFix":"// before\n_ => {\n    bail!(\"Unexpected node body for stream cdc scan\");\n}\n// after\nStreamNodeBody::SomeNewVariant(..) => {\n    // treat as scan-like body\n    found_cdc_scan = found_cdc_scan || contains_cdc_scan(node);\n}\n_ => bail!(\"Unexpected node body for stream cdc scan\"),","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_cdc_scan_body(body: &StreamNodeBody) -> bool {\n    matches!(body, StreamNodeBody::StreamCdcScan(..))\n}","tryCatchPattern":"match create_cdc_table(...).await {\n    Err(e) if e.to_string().contains(\"Unexpected node body for stream cdc scan\") => {\n        // verify frontend/meta version alignment, then report/upgrade\n    }\n    other => other?,\n}","preventionTips":["Keep frontend and meta node versions in lockstep","After upgrades, test CDC table creation before production use","Capture the fragment graph when reporting the bug"],"tags":["cdc","validation","internal"],"backgroundTag":"unexpected-response-shape","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"}