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

  1. Align the declared RisingWave column type with the Iceberg transform's result type (e.g. day-transform on date/timestamp should be INT).
  2. Check the transform argument string for typos (year/month/day/hour/identity/truncate/bucket).
  3. Verify input type is compatible with the chosen transform (e.g. truncate on strings vs numerics).
  4. 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

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


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)