{"record":{"id":"b2d44fb52ea5d29d","repo":"risingwavelabs/risingwave","slug":"data-type-must-be-datatype-list","errorCode":null,"errorMessage":"data type must be DataType::List","messagePattern":"data type must be DataType::List","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/macro/src/gen.rs","lineNumber":532,"sourceCode":"        };\n        // the output expression in `eval_row`\n        let row_output = match user_fn.writer_type_kind {\n            Some(WriterTypeKind::FmtWrite) => quote! {{\n                let mut writer = String::new();\n                #output.map(|_| writer.into())\n            }},\n            Some(WriterTypeKind::IoWrite) => quote! {{\n                let mut writer = Vec::new();\n                #output.map(|_| writer.into())\n            }},\n            Some(WriterTypeKind::JsonbbBuilder) => quote! {{\n                let mut writer = jsonbb::Builder::<Vec<u8>>::new();\n                #output.map(|_| JsonbVal::from(writer.finish()).into())\n            }},\n            Some(WriterTypeKind::ListWrite) => quote! {{\n                let mut writer = {\n                    let DataType::List(list_ty) = &self.context.return_type else {\n                        panic!(\"data type must be DataType::List\");\n                    };\n                    list_ty.elem().create_array_builder(1)\n                };\n                #output.map(|_| ListValue::new(writer.finish()).into())\n            }},\n            None if user_fn.core_return_type == \"impl AsRef < [u8] >\" => quote! {\n                #output.map(|s| s.as_ref().into())\n            },\n            None => quote! {{\n                let output #annotation = #output;\n                output.map(|s| s.into())\n            }},\n        };\n        // the main body in `eval`\n        let eval = if let Some(batch_fn) = &self.batch_fn {\n            assert!(\n                !variadic,\n                \"customized batch function is not supported for variadic functions\"","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/macro/src/gen.rs#L514-L550","documentation":"For functions returning `impl Iterator` with ListWrite output, the generated code needs the return type to be `DataType::List` to create an element array builder. If `return_type` is not a List, the generated code panics with `data type must be DataType::List` at runtime.","triggerScenarios":"A scalar function declared with `#[return_type = \"list\"]`/ListWrite writer whose actual inferred return type is not a List — e.g. type inference returns a scalar or struct type for a function generating list output.","commonSituations":"Custom type_infer returning the wrong type for a list-producing function; frontend infers a non-list return for a UDF that uses the ListWrite writer path.","solutions":["Fix the type_infer function to always return DataType::List for this function","Fix the frontend inference so the return type is a List","Guard the generated code with a clear error instead of panic if the type can vary"],"exampleFix":"// before\ntype_infer = \"|_| Ok(DataType::Varchar)\"\n// after\ntype_infer = \"|_| Ok(DataType::List(Box::new(DataType::Varchar.into())))\"","handlingStrategy":"validation","validationCode":"fn ensure_list_return(rt: &DataType) -> Result<(), String> {\n    match rt { DataType::List(_) => Ok(()), other => Err(format!(\"return type must be List, got {other:?}\")) }\n}","typeGuard":"fn as_list_type(rt: &DataType) -> Option<&ListType> { match rt { DataType::List(l) => Some(l), _ => None } }","tryCatchPattern":"match as_list_type(&func.return_type()) {\n    None => return Err(\"function must return a list\".into()),\n    Some(list_ty) => run_list_write_udf(list_ty),\n}","preventionTips":["Ensure type_infer returns DataType::List for ListWrite functions","Add a unit test asserting the inferred return type is a list","Document writer-kind requirements in the function declaration"],"tags":["proc-macro","type-inference","list"],"backgroundTag":"type-mismatch","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"}