risingwavelabs/risingwave · error · Internal
eval_row in iceberg_transform is not supported yet
Error message
eval_row in iceberg_transform is not supported yet
What it means
The iceberg_transform expression only implements row-batch (array) evaluation; its eval_row path is deliberately unimplemented and always returns this internal error. Row-at-a-time evaluation of Iceberg partition transforms is not supported.
Solutions
- Evaluate the expression via the array/batch path (eval) instead of eval_row.
- If you must evaluate row-wise, wrap the row in a single-row array and call eval.
- If this is a legitimate need, file/await upstream support for eval_row in iceberg_transform.
Example fix
// before let datum = expr.eval_row(&row)?; // after let array = expr.eval(&single_row_array)?; let datum = array.value_at(0).to_owned_datum();
Defensive patterns
Strategy: fallback
Validate before calling
// Avoid row-wise evaluation of iceberg_transform; use batch eval: // let array = expr.eval(&input_array)?;
Try / catch
match expr.eval_row(row) {
Ok(d) => d,
Err(e) if e.to_string().contains("not supported") => {
// fall back to batch evaluation
let arr = expr.eval(&single_row_array)?;
arr.value_at(0).to_owned_datum()
}
Err(e) => return Err(e),
} Prevention
- Never call eval_row on external/iceberg_transform expressions.
- Route iceberg_transform through batch (array) evaluation paths only.
- Check expression kind before choosing row vs array evaluation in generic executor code.
When it happens
Trigger: Evaluating an iceberg_transform expression through the sync/row evaluation path — e.g. code that calls ExprVisitor::eval_row or evaluates the expression against a single OwnedRow instead of an array.
Common situations: New executor or tooling code path that evaluates expressions per-row rather than per-batch; using iceberg_transform in a context (e.g. some UDF wrappers or row-based joins) that requires eval_row.
Related errors
- async child in iceberg_transform is not supported
- not implemented
- not yet implemented
- adlsgen2.authority_host does not parse as a URL
- adlsgen2.authority_host must not contain a path component
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/70e92a4b06da69bf.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/scalar/external/iceberg.rs:73
}
}
impl SyncExpression for IcebergTransform {
fn eval(&self, data_chunk: &DataChunk) -> Result<ArrayRef> {
let array = self.child.eval(data_chunk)?;
// Convert to arrow array
let arrow_array = IcebergArrowConvert.to_arrow_array(&self.input_arrow_type, &array)?;
// Transform
let res_array = self.transform.transform(arrow_array).unwrap();
// Convert back to array ref and return it
Ok(Arc::new(IcebergArrowConvert.array_from_arrow_array(
&self.output_arrow_field,
&res_array,
)?))
}
fn eval_row(&self, _row: &OwnedRow) -> Result<Datum> {
Err(ExprError::Internal(anyhow!(
"eval_row in iceberg_transform is not supported yet"
)))
}
}
#[build_function("iceberg_transform(varchar, any) -> any", type_infer = "unreachable")]
fn build(return_type: DataType, mut children: Vec<BoxedExpression>) -> Result<BoxedExpression> {
let transform_type = {
let datum = children[0].eval_const()?.unwrap();
let str = datum.as_utf8();
Transform::from_str(str).map_err(|_| ExprError::InvalidParam {
name: "transform type in iceberg_transform",
reason: format!("Fail to parse {str} as iceberg transform type").into(),
})?
};
// For Identity and Void transform, we will use `InputRef` and const null in frontend,
// so it should not reach here.View on GitHub (pinned to 6469eb736d)