risingwavelabs/risingwave · error · anyhow::Error

field {}'s type is incompatible RisingWave converted data ty

Error message

field {}'s type is incompatible
RisingWave converted data type: {}
iceberg's data type: {}

What it means

When a column exists in both schemas but its types are not compatible, `check_compatibility` bails with a detailed message listing the RisingWave-converted Arrow data type and the Iceberg table's Arrow data type. This is the sink refusing to write into a table whose column type cannot accept RisingWave's data.

Source

Thrown at src/connector/src/sink/iceberg/create_table.rs:382

            Ok(true)
        }
        (_, left, right) => Ok(left.equals_datatype(right)),
    }
}

fn check_compatibility(
    schema_fields: HashMap<&str, &risingwave_common::types::DataType>,
    fields: &ArrowFields,
) -> anyhow::Result<bool> {
    for arrow_field in fields {
        let our_field_type = schema_fields
            .get(arrow_field.name().as_str())
            .ok_or_else(|| anyhow!("Field {} not found in our schema", arrow_field.name()))?;

        if !field_is_compatible(our_field_type, arrow_field)? {
            let converted_arrow_data_type = IcebergArrowConvert
                .to_arrow_field("", our_field_type)
                .map_err(|e| anyhow!(e))?
                .data_type()
                .clone();
            bail!(
                "field {}'s type is incompatible\nRisingWave converted data type: {}\niceberg's data type: {}",
                arrow_field.name(),
                converted_arrow_data_type,
                arrow_field.data_type()
            );
        }
    }
    Ok(true)
}

/// Try to match our schema with iceberg schema.
pub fn try_matches_arrow_schema(rw_schema: &Schema, arrow_schema: &ArrowSchema) -> Result<()> {
    if rw_schema.fields.len() != arrow_schema.fields().len() {
        bail!(
            "Schema length mismatch, risingwave is {}, and iceberg is {}",

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Compare the two printed data types in the message and CAST the sink column to match the Iceberg table type.
  2. If you own the table, recreate the Iceberg table with types derived from the RW schema (let RW create the table).
  3. For VARIANT columns, ensure both sides are VARIANT (plain structs won't be accepted).
  4. Ensure nested struct field names and order match exactly, since structs are compared positionally.

Example fix

// before: RW column is INTEGER, Iceberg table column is STRING
CREATE SINK s AS SELECT id FROM t;
// after
CREATE SINK s AS SELECT id::VARCHAR AS id FROM t;
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate each column type against the table before creating the sink
for (name, rw_t, arrow_f) in pairs {
    if !field_is_compatible(rw_t, arrow_f)? {
        eprintln!("column {name}: RW {:?} vs table {}", rw_t, arrow_f.data_type());
    }
}

Prevention

When it happens

Trigger: Called from `try_matches_arrow_schema`: `field_is_compatible` returns false for a column — e.g., RW INT vs Iceberg STRING, mismatched struct field names/order, mismatched list element types, VARIANT vs non-VARIANT.

Common situations: Creating a sink into a pre-existing Iceberg table with different column types; type changed in RisingWave after the Iceberg table was created; nested struct/list type drift; decimal precision differences are tolerated but other type differences are not.

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/a1dab69759d77d1d. Report an issue: GitHub.