{"record":{"id":"65d93a0e9dce938a","repo":"risingwavelabs/risingwave","slug":"no-stream-cdc-scan-node-found-in-stream-scan-fragm","errorCode":null,"errorMessage":"No stream cdc scan node found in stream scan fragment","messagePattern":"No stream cdc scan node found in stream scan fragment","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/rpc/ddl_controller.rs","lineNumber":1053,"sourceCode":"            }\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(),\n                cdc_table_desc.secret_refs.clone(),\n            );\n\n            let mut props = ConnectorProperties::extract(options_with_secret, true)?;","sourceCodeStart":1035,"sourceCodeEnd":1071,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/rpc/ddl_controller.rs#L1035-L1071","documentation":"validate_cdc_table walks the stream scan fragment looking for a StreamCdcScan node and fails if none is found. This means the plan generated for a CDC table lacks the required CDC scan operator, so meta refuses to create the streaming job rather than build a table that cannot consume CDC events.","triggerScenarios":"Creating a CDC table where the stream scan fragment contains no StreamCdcScan node — e.g. the frontend produced a wrong plan for the CDC source, or validation is applied to a fragment type that never contains a cdc scan.","commonSituations":"Bugs in CDC plan generation after frontend changes; applying a CDC table on a source that got rewritten to a different operator; version mismatch between frontend and meta binaries.","solutions":["Verify frontend and meta are the same version and rebuild/redeploy consistently.","Check the generated plan (EXPLAIN or fragment view) to confirm whether a cdc scan exists upstream; fix the source/connector definition.","If triggered by a code change, extend or correct the plan so the CDC table includes a StreamCdcScan node."],"exampleFix":"// before: validating an arbitrary scan fragment without a cdc scan node\n// after: ensure the table is created with a proper CDC source so the plan contains StreamCdcScan\nCREATE TABLE t (...) WITH (\n   connector = 'cdc-postgres', ...\n) FROM pg_source;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = create_cdc_table(...).await {\n    if e.to_string().contains(\"No stream cdc scan node found\") {\n        // check source is a proper CDC source and versions match\n    }\n}","preventionTips":["Create CDC tables only from proper CDC sources/connector definitions","Pin consistent frontend/meta versions","Use EXPLAIN/fragment view to verify cdc scan presence when debugging"],"tags":["cdc","validation","plan"],"backgroundTag":"schema-validation-failed","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}