databendlabs/databend · error
unexpected value type for grouping function
Error message
unexpected value type for grouping function: {:?} What it means
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.
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.
Example fix
// before
v => unreachable!("unexpected value type for grouping function: {:?}", v),
// after
Value::Scalar(s) => {
let out = compute_grouping(¶ms, s_as_u32(&s));
Value::Column(Column::Number(NumberColumn::UInt32(vec![out])))
}
v => Err(ErrorCode::BadArguments(format!(
"unexpected value type for grouping function: {:?}", v))), Defensive patterns
Strategy: type-guard
Validate before calling
// Guard the argument shape before invoking the grouping evaluator:
fn is_grouping_column(v: &Value) -> bool {
matches!(v, Value::Column(Column::Number(_)))
} Type guard
fn as_grouping_column(v: &Value) -> Option<&Column> {
match v {
Value::Column(c @ Column::Number(_)) => Some(c),
_ => None,
}
} Try / catch
// Panics are not catchable in Rust by default; isolate evaluation:
let result = std::panic::catch_unwind(|| grouping_eval(&args));
match result {
Ok(v) => v,
Err(_) => return Err(ErrorCode::BadArguments("grouping arg must be a number column")),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- grouping function must be rewritten in type_checker, but got
- Unsupported unit
- internal error: entered unreachable code
- internal error: entered unreachable code
- internal error: entered unreachable code
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/1b456282dd8a481b.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/functions/src/scalars/other.rs:413
signature: FunctionSignature {
name: "grouping".to_string(),
args_type: vec![DataType::Number(NumberDataType::UInt32)],
return_type: DataType::Number(NumberDataType::UInt32),
},
eval: FunctionEval::Scalar {
calc_domain: Box::new(FunctionDomain::Full),
eval: scalar_evaluator(move |args, _| match &args[0] {
Value::Scalar(Scalar::Number(NumberScalar::UInt32(v))) => Value::Scalar(
Scalar::Number(NumberScalar::UInt32(compute_grouping(¶ms, *v))),
),
Value::Column(Column::Number(NumberColumn::UInt32(col))) => {
let output = col
.iter()
.map(|v| compute_grouping(¶ms, *v))
.collect::<Vec<_>>();
Value::Column(Column::Number(NumberColumn::UInt32(output.into())))
}
v => unreachable!("unexpected value type for grouping function: {:?}", v),
}),
derive_stat: None,
},
}))
}));
registry.register_function_factory("grouping", grouping);
// dummy grouping
// used in type_check before AggregateRewriter
let dummy_grouping = FunctionFactory::Closure(Box::new(|_, arg_type: &[DataType]| {
Some(Arc::new(Function {
signature: FunctionSignature {
name: "grouping".to_string(),
args_type: vec![DataType::Generic(0); arg_type.len()],
return_type: DataType::Number(NumberDataType::UInt32),
},
eval: FunctionEval::Scalar {
calc_domain: Box::new(FunctionDomain::Full),View on GitHub (pinned to 288d84d76e)