{"record":{"id":"1b456282dd8a481b","repo":"databendlabs/databend","slug":"unexpected-value-type-for-grouping-function","errorCode":null,"errorMessage":"unexpected value type for grouping function: {:?}","messagePattern":"unexpected value type for grouping function: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/functions/src/scalars/other.rs","lineNumber":413,"sourceCode":"            signature: FunctionSignature {\n                name: \"grouping\".to_string(),\n                args_type: vec![DataType::Number(NumberDataType::UInt32)],\n                return_type: DataType::Number(NumberDataType::UInt32),\n            },\n            eval: FunctionEval::Scalar {\n                calc_domain: Box::new(FunctionDomain::Full),\n                eval: scalar_evaluator(move |args, _| match &args[0] {\n                    Value::Scalar(Scalar::Number(NumberScalar::UInt32(v))) => Value::Scalar(\n                        Scalar::Number(NumberScalar::UInt32(compute_grouping(&params, *v))),\n                    ),\n                    Value::Column(Column::Number(NumberColumn::UInt32(col))) => {\n                        let output = col\n                            .iter()\n                            .map(|v| compute_grouping(&params, *v))\n                            .collect::<Vec<_>>();\n                        Value::Column(Column::Number(NumberColumn::UInt32(output.into())))\n                    }\n                    v => unreachable!(\"unexpected value type for grouping function: {:?}\", v),\n                }),\n                derive_stat: None,\n            },\n        }))\n    }));\n    registry.register_function_factory(\"grouping\", grouping);\n\n    // dummy grouping\n    // used in type_check before AggregateRewriter\n    let dummy_grouping = FunctionFactory::Closure(Box::new(|_, arg_type: &[DataType]| {\n        Some(Arc::new(Function {\n            signature: FunctionSignature {\n                name: \"grouping\".to_string(),\n                args_type: vec![DataType::Generic(0); arg_type.len()],\n                return_type: DataType::Number(NumberDataType::UInt32),\n            },\n            eval: FunctionEval::Scalar {\n                calc_domain: Box::new(FunctionDomain::Full),","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/functions/src/scalars/other.rs#L395-L431","documentation":"The `grouping` scalar function factory in src/query/functions/src/scalars/other.rs registers an evaluator that expects the GROUPING argument to arrive as a column value it can iterate; any other `Value` variant (e.g. a scalar Value instead of Value::Column, or another column type) triggers `unreachable!(\"unexpected value type for grouping function: {:?}\")`. It is an internal invariant that the type checker/binder normalized arguments before scalar evaluation.","triggerScenarios":"Executing a GROUPING(...) call whose argument reaches scalar evaluation as a Value variant other than Value::Column backed by NumberColumn (e.g. a constant-folded scalar, nullable/large-list column, or a Value::Scalar from const evaluation) instead of being rewritten by the type checker.","commonSituations":"Query plans where GROUPING's argument was constant-folded before evaluation; new column encodings introduced after this code was written; calling the registered function factory directly from custom tooling or tests with hand-built arguments.","solutions":["Ensure the GROUPING function is rewritten during type checking before scalar evaluation runs (see error 57's companion unreachable).","Inspect the logged value shape in the panic message and add a matching match arm (e.g. Value::Scalar) with correct semantics if that shape is legitimate.","If invoking the factory directly, construct arguments as Value::Column(Column::Number(NumberColumn::UInt32/...)) as the evaluator expects.","Convert the unreachable!() into a returned FunctionError so malformed input fails gracefully."],"exampleFix":"// before\nv => unreachable!(\"unexpected value type for grouping function: {:?}\", v),\n// after\nValue::Scalar(s) => {\n    let out = compute_grouping(&params, s_as_u32(&s));\n    Value::Column(Column::Number(NumberColumn::UInt32(vec![out])))\n}\nv => Err(ErrorCode::BadArguments(format!(\n    \"unexpected value type for grouping function: {:?}\", v))),","handlingStrategy":"type-guard","validationCode":"// Guard the argument shape before invoking the grouping evaluator:\nfn is_grouping_column(v: &Value) -> bool {\n    matches!(v, Value::Column(Column::Number(_)))\n}","typeGuard":"fn as_grouping_column(v: &Value) -> Option<&Column> {\n    match v {\n        Value::Column(c @ Column::Number(_)) => Some(c),\n        _ => None,\n    }\n}","tryCatchPattern":"// Panics are not catchable in Rust by default; isolate evaluation:\nlet result = std::panic::catch_unwind(|| grouping_eval(&args));\nmatch result {\n    Ok(v) => v,\n    Err(_) => return Err(ErrorCode::BadArguments(\"grouping arg must be a number column\")),\n}","preventionTips":["Always run plans through the standard binder/type_checker before function evaluation.","Never call registered function evaluators with hand-built Values; use the planner APIs.","When adding column encodings, audit scalar evaluators that match on Value variants."],"tags":["sql-functions","rust","panic","grouping","internal-invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}