risingwavelabs/risingwave · error · Internal
async child in iceberg_transform is not supported
Error message
async child in iceberg_transform is not supported
What it means
iceberg_transform requires its value child expression to be a synchronous expression. If the second child is an async expression (BoxedExpression::Async), the builder refuses it because the transform is evaluated synchronously and cannot await.
Solutions
- Materialize the async expression's result into a regular column/expression before applying iceberg_transform.
- Restructure the plan so the transform input comes from a synchronous source (table column or computed expression).
- If async input is genuinely required, extend iceberg_transform to support BoxedExpression::Async evaluation.
Example fix
// before
let child = children.remove(1); // may be BoxedExpression::Async
// after
let child = match children.remove(1) {
BoxedExpression::Sync(c) => c,
_ => return Err(/* materialize async input first */),
}; Defensive patterns
Strategy: type-guard
Validate before calling
if matches!(children[1], BoxedExpression::Async(_)) {
return Err("iceberg_transform input must be a sync expression".into());
} Type guard
fn is_sync(e: &BoxedExpression) -> bool { matches!(e, BoxedExpression::Sync(_)) } Prevention
- Keep iceberg_transform inputs as plain column references or sync computed expressions.
- Materialize async expression results into columns before applying partition transforms.
- Review planner rules that may wrap transform inputs in async lookup expressions.
When it happens
Trigger: Building iceberg_transform(varchar, any) where children.remove(1) is an async expression — e.g. the input column expression is produced by an async lookup/UDF expression rather than a plain column reference.
Common situations: Composing iceberg_transform over the output of an async UDF or I/O-bound expression; planner rewrites that wrap the input in an async lookup expression.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- eval_row in iceberg_transform is not supported yet
- adlsgen2.authority_host does not parse as a URL
- adlsgen2.authority_host must not contain a path component
- adlsgen2.authority_host must not contain a query or fragment
- adlsgen2.authority_host must not contain userinfo
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/170bc1f85888af89.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/scalar/external/iceberg.rs:161
(matches!(transform_type, Transform::Day) && matches!(actual_res_type, IcebergType::Primitive(PrimitiveType::Int))),
ExprError::InvalidParam {
name: "return type in iceberg_transform",
reason: format!(
"Expect return type {:?} but got {:?}, RisingWave return type is {:?}, input type is {:?}, transform type is {:?}",
expect_res_type,
actual_res_type,
return_type,
(input_type, input_arrow_type),
transform_type
)
.into()
}
);
let child = match children.remove(1) {
BoxedExpression::Sync(child) => child,
BoxedExpression::Async(_) => {
return Err(ExprError::Internal(anyhow!(
"async child in iceberg_transform is not supported"
)));
}
};
let transform = create_transform_function(&transform_type)
.map_err(|err| ExprError::Internal(err.into()))?;
Ok(IcebergTransform {
child,
transform,
input_arrow_type,
output_arrow_field,
return_type,
}
.boxed())
}
#[cfg(test)]
mod test {View on GitHub (pinned to 6469eb736d)