risingwavelabs/risingwave · error · InvalidParam
Expect return type but got , RisingWave return type is …
Error message
Expect return type {:?} but got {:?}, RisingWave return type is {:?}, input type is {:?}, transform type is {:?} What it means
The iceberg_transform builder checks that the Iceberg transform's result type matches the expected RisingWave return type. Mismatch raises InvalidParam with a detailed comparison of expected vs actual Iceberg type, the RisingWave return type, input type, and transform. The Transform::Day special case allows Int because Iceberg's day transform yields an int per apache/iceberg#11749.
Solutions
- Align the declared RisingWave column type with the Iceberg transform's result type (e.g. day-transform on date/timestamp should be INT).
- Check the transform argument string for typos (year/month/day/hour/identity/truncate/bucket).
- Verify input type is compatible with the chosen transform (e.g. truncate on strings vs numerics).
- If on an older Iceberg spec mapping, upgrade/adjust code to account for the day->Int convention (PR #11749).
Example fix
// before CREATE TABLE t (ts TIMESTAMP, PRIMARY KEY (x)) PARTITIONED BY (day(ts) AS VARCHAR) // after -- declare the partition/result column as INT for day transform PARTITIONED BY (day(ts)) -- result type INT
Defensive patterns
Strategy: validation
Validate before calling
// Before DDL: verify the partition transform's Iceberg result type matches the RW column type
let actual = transform.result_type(input_type)?;
let compatible = actual == expected
|| (matches!(transform, Transform::Day) && matches!(actual, IcebergType::Primitive(PrimitiveType::Int)));
if !compatible { return Err(format!("{transform:?} of {input_type:?} yields {actual:?}, expected {expected:?}")); } Prevention
- Map each Iceberg transform to its documented result type when declaring partition columns.
- Remember day(ts) yields INT, not DATE, in the Iceberg spec.
- Test partition DDL against a small table before applying to production schemas.
When it happens
Trigger: Calling build for `iceberg_transform(varchar, any)` where the transform function's output IcebergType differs from the type inferred from the RisingWave return type — e.g. transform `year` on a timestamp with a VARCHAR RisingWave result, or a day transform whose result is not mapped to Int correctly.
Common situations: Defining an Iceberg partition table where the RisingWave column type doesn't match the Iceberg partition field's transformed type; Iceberg spec/version mismatches around transform result types; hand-written DDL declaring the wrong result type.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- error converting StreamChunk to Arrow RecordBatch
- failed to add partition columns
- field 's type is incompatible RisingWave converted data…
- materialize pk-index sink SerializedDataFile
- partition_spec_id should be a u64
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/aede97503be50761.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/scalar/external/iceberg.rs:144
.to_arrow_field("", &return_type)?
.data_type()
.clone(),
)
.map_err(|err| ExprError::InvalidParam {
name: "return type in iceberg_transform",
reason: format!(
"Failed to convert return type to iceberg type, got error: {}",
err.as_report()
)
.into(),
})?;
ensure!(
(expect_res_type == actual_res_type)
||
// This is a confusing stuff.<https://github.com/apache/iceberg/pull/11749>
(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"View on GitHub (pinned to 6469eb736d)