risingwavelabs/risingwave · error
aggregate function is not supported
Error message
aggregate function is not supported
What it means
The default trait implementation of `call_agg_create_state` on RisingWave's UDF expression trait always fails with this message. It exists so scalar/table UDFs only need to implement aggregate hooks when they actually represent an aggregate function; calling the aggregate path on a UDF that did not override it hits this bail.
Source
Thrown at src/expr/core/src/sig/udf.rs:142
Table,
Aggregate,
}
/// UDF implementation.
#[async_trait::async_trait]
pub trait UdfImpl: std::fmt::Debug + Send + Sync {
/// Call the scalar function.
async fn call(&self, input: &RecordBatch) -> Result<RecordBatch>;
/// Call the table function.
async fn call_table_function<'a>(
&'a self,
input: &'a RecordBatch,
) -> Result<BoxStream<'a, Result<RecordBatch>>>;
/// For aggregate function, create the initial state.
async fn call_agg_create_state(&self) -> Result<ArrayRef> {
bail!("aggregate function is not supported");
}
/// For aggregate function, accumulate or retract the state.
async fn call_agg_accumulate_or_retract(
&self,
_state: &ArrayRef,
_ops: &BooleanArray,
_input: &RecordBatch,
) -> Result<ArrayRef> {
bail!("aggregate function is not supported");
}
/// For aggregate function, get aggregate result from the state.
async fn call_agg_finish(&self, _state: &ArrayRef) -> Result<ArrayRef> {
bail!("aggregate function is not supported");
}
/// Whether the UDF talks in legacy mode.View on GitHub (pinned to 6469eb736d)
Solutions
- Implement `call_agg_create_state` (plus `call_agg_accumulate_or_retract` and `call_agg_finish`) for the UDF if it is meant to be an aggregate.
- If the UDF is scalar-only, fix the query/planning so it is not used as an aggregate (or register it with the correct function kind).
- Verify the UDF descriptor/kind in the function catalog declares `AGGREGATE` only when the aggregate trait methods are provided.
Example fix
// before
impl UdfImpl for MyUdf {
async fn eval(&self, input: &RecordBatch) -> Result<ArrayRef> { /* scalar eval */ }
}
// after
#[async_trait]
impl UdfImpl for MyUdf {
async fn eval(&self, input: &RecordBatch) -> Result<ArrayRef> { /* scalar eval */ }
async fn call_agg_create_state(&self) -> Result<ArrayRef> {
Ok(self.state_builder.build_initial_state())
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: check trait capabilities before aggregate use
fn supports_aggregate(u: &dyn UdfImpl) -> bool { u.implements_agg() } Type guard
fn is_aggregate_udf(f: &FunctionDesc) -> bool { matches!(f.kind, FunctionKind::Aggregate) } Try / catch
match udf.call_agg_create_state().await {
Ok(state) => state,
Err(e) if e.to_string().contains("aggregate function is not supported") => {
return Err(anyhow!("UDF '{}' cannot be used as an aggregate", name));
}
Err(e) => return Err(e.into()),
} Prevention
- Only declare a function AGGREGATE in the catalog when all aggregate trait methods are implemented
- Add a unit test that calls all three agg hooks for every aggregate UDF
- Keep scalar and aggregate UDFs in separate registration paths
When it happens
Trigger: Calling `call_agg_create_state()` on a `UdfExpr`/UDF wrapper whose underlying implementation only overrides the scalar (or table-function) evaluation methods and leaves `call_agg_create_state` as the trait default — e.g. running the aggregate streaming/batch executor over an external UDF registered as a scalar function.
Common situations: A developer registers a Python/SQL/external UDF intended to be used with GROUP BY aggregation but implements it as a scalar UDF; or a planner/executor bug routes an aggregate call down the UDF path without the aggregate trait methods being implemented.
Related errors
- Only AddColumns schema change is supported for Redshift sink
- UDF returned a value of type {} while the declared return ty
- UDF aggregate {what} has {} rows, but expected exactly 1
- {0}
- UDF returned {} rows, but expected {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/4eeaa02f7ba3e681.
Report an issue: GitHub.