{"record":{"id":"f124172d6faa8ad6","repo":"risingwavelabs/risingwave","slug":"generateseriesexecutor-should-not-have-child","errorCode":null,"errorMessage":"GenerateSeriesExecutor should not have child!","messagePattern":"GenerateSeriesExecutor should not have child!","errorType":"validation","errorClass":"BatchError","httpStatus":null,"severity":"error","filePath":"src/batch/executors/src/executor/table_function.rs","lineNumber":75,"sourceCode":"            // remove the first column and expand the second column if its data type is struct\n            yield match chunk.column_at(1).as_ref() {\n                ArrayImpl::Struct(struct_array) => struct_array.into(),\n                _ => chunk.split_column_at(1).1,\n            };\n        }\n    }\n}\n\npub struct TableFunctionExecutorBuilder {}\n\nimpl TableFunctionExecutorBuilder {}\n\nimpl BoxedExecutorBuilder for TableFunctionExecutorBuilder {\n    async fn new_boxed_executor(\n        source: &ExecutorBuilder<'_>,\n        inputs: Vec<BoxedExecutor>,\n    ) -> Result<BoxedExecutor> {\n        ensure!(\n            inputs.is_empty(),\n            \"GenerateSeriesExecutor should not have child!\"\n        );\n        let node = try_match_expand!(\n            source.plan_node().get_node_body().unwrap(),\n            NodeBody::TableFunction\n        )?;\n\n        let identity = source.plan_node().get_identity().clone();\n\n        let chunk_size = source.context().get_config().developer.chunk_size;\n\n        let table_function = build_from_prost(node.table_function.as_ref().unwrap(), chunk_size)?;\n\n        let schema = if let DataType::Struct(fields) = table_function.return_type() {\n            (&fields).into()\n        } else {\n            Schema {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/executors/src/executor/table_function.rs#L57-L93","documentation":"TableFunctionExecutorBuilder (e.g. generate_series) requires zero child executors. Table functions are leaf operators whose output rows are generated from their expression arguments, so an input executor means the plan incorrectly wired a child under the table function node.","triggerScenarios":"new_boxed_executor is invoked with a non-empty `inputs` vec because a TableFunction plan node has children in the batch plan tree.","commonSituations":"Planner bugs when planning queries with generate_series/unnest-style table functions; incorrectly nesting a table function under another operator in hand-built plans; test fixtures wiring children into leaf nodes.","solutions":["Check the plan: the TableFunction node must have no children; fix the planner code that produced a child.","Ensure table-function arguments are passed as expressions (value_node.relation_expr), not as child executors.","When building TableFunctionExecutor manually, supply an empty inputs vector.","File an internal bug with the reproducing SQL if the planner looks correct."],"exampleFix":"// before: child executor fed to table function\nlet inputs = vec![child_executor];\n// after: table function as leaf, data via expression arguments\nlet inputs = vec![];","handlingStrategy":"try-catch","validationCode":"// Rust: table functions must have no child executors\nassert!(inputs.is_empty(), \"TableFunction must be a leaf node\");","typeGuard":"fn is_leaf(inputs: &[BoxedExecutor]) -> bool { inputs.is_empty() }","tryCatchPattern":"match builder.new_boxed_executor(&src, inputs).await {\n    Err(e) if e.to_string().contains(\"should not have child\") => /* fix plan arity, log plan tree */,\n    other => other,\n}","preventionTips":["Pass table function arguments as expressions, never as child executors.","Add planner tests for generate_series/unnest queries.","Check plan-node arity after any frontend refactor."],"tags":["batch-executor","table-function","generate-series","planner","rust"],"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"}