{"record":{"id":"90be4c620d95ed93","repo":"risingwavelabs/risingwave","slug":"logstore-row-sequential-scan-should-not-have-input","errorCode":null,"errorMessage":"LogStore row sequential scan should not have input executor!","messagePattern":"LogStore row sequential scan should not have input executor!","errorType":"validation","errorClass":"BatchError","httpStatus":null,"severity":"error","filePath":"src/batch/executors/src/executor/log_row_seq_scan.rs","lineNumber":100,"sourceCode":"            metrics,\n            table,\n            old_epoch,\n            new_epoch,\n            version_id,\n            ordered,\n            scan_range,\n        }\n    }\n}\n\npub struct LogStoreRowSeqScanExecutorBuilder {}\n\nimpl BoxedExecutorBuilder for LogStoreRowSeqScanExecutorBuilder {\n    async fn new_boxed_executor(\n        source: &ExecutorBuilder<'_>,\n        inputs: Vec<BoxedExecutor>,\n    ) -> Result<BoxedExecutor> {\n        ensure!(\n            inputs.is_empty(),\n            \"LogStore row sequential scan should not have input executor!\"\n        );\n        let log_store_seq_scan_node = try_match_expand!(\n            source.plan_node().get_node_body().unwrap(),\n            NodeBody::LogRowSeqScan\n        )?;\n\n        let table_desc: &StorageTableDesc = log_store_seq_scan_node.get_table_desc()?;\n        let column_ids = log_store_seq_scan_node\n            .column_ids\n            .iter()\n            .copied()\n            .map(ColumnId::from)\n            .collect();\n\n        let vnodes = match &log_store_seq_scan_node.vnode_bitmap {\n            Some(vnodes) => Some(Bitmap::from(vnodes).into()),","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/executors/src/executor/log_row_seq_scan.rs#L82-L118","documentation":"The `LogStoreRowSeqScanExecutorBuilder::new_boxed_executor` asserts that the LogRowSeqScan plan node receives no child executors, because a log store row sequential scan reads directly from the log store and cannot consume upstream input. Receiving an `inputs` vector that is non-empty means the distributed plan is malformed, so building the executor fails.","triggerScenarios":"Executing a batch plan where a `LogRowSeqScan` node has a child in the plan tree — e.g. a malformed Fragment/PlanNode protobuf where the exchange wiring attaches a child under the log-row-seq-scan node instead of under an exchange.","commonSituations":"Bugs or version skew in plan distribution between meta and compute nodes; corrupted or hand-modified plan fragments in tests or debugging tools; custom schedulers that mis-assemble the executor tree.","solutions":["Inspect the failing batch task's plan (check meta logs / `explain`) and remove any child executor wired beneath the LogRowSeqScan node.","Upgrade all nodes to matching versions to rule out plan-format skew between meta and compute.","If it reproduces, capture the plan fragment and file a RisingWave issue — this indicates a plan-assembly bug, not user data."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// validate plan shape before dispatching the fragment\nfn assert_leaf(node: &PlanNode) -> Result<()> {\n    ensure!(node.children.is_empty(), \"LogRowSeqScan must be a leaf node\");\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not modify plan fragments by hand; treat distributed plans as produced by meta only.","Keep all node versions aligned to avoid plan-format skew.","Validate plan fragments in tests by asserting leaf executors have no children."],"tags":["batch-executor","plan-validation","logstore","internal-invariant"],"backgroundTag":"internal-invariant-violation","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"}