risingwavelabs/risingwave · error · SinkError::SqlServer

column data type is incompatible with downstream SQL Server…

Error message

column {} data type {:?} is incompatible with downstream SQL Server type {}

What it means

During sink validation, each RisingWave column's data type is compared against the downstream SQL Server column's type via `sql_server_data_type_is_compatible`. If incompatible, this error names the column, the RW type (`{:?}` debug format), and the SQL Server type string. This preflight prevents runtime write failures or silent data corruption from type mismatches.

Solutions

  1. ALTER the downstream SQL Server column type to match the RW type shown in the error (e.g. `ALTER TABLE t ALTER COLUMN c BIGINT;`).
  2. Or cast the column in the RW materialized view to match the downstream type before sinking.
  3. Compare against the compatibility matrix in `sql_server_data_type_is_compatible` to pick a supported pair.
  4. Drop and recreate the sink after aligning schemas so validation re-runs cleanly.

Example fix

// RW column: amount DECIMAL(18,2), downstream: FLOAT
-- before
CREATE TABLE dbo.orders (amount FLOAT);
-- after
ALTER TABLE dbo.orders ALTER COLUMN amount DECIMAL(18,2);
Defensive patterns

Strategy: validation

Validate before calling

-- compare column types on both sides before CREATE SINK
SELECT c.name, ty.name AS sqlserver_type
FROM sys.columns c JOIN sys.types ty ON ty.user_type_id = c.user_type_id
JOIN sys.tables t ON t.object_id = c.object_id
WHERE t.name = 'orders';

Try / catch

match sink.validate().await {
    Err(e) if e.to_string().contains("is incompatible with downstream SQL Server type") => {
        reconcile_column_types(&parse_column_from_error(&e.to_string()));
    }
    other => other,
}

Prevention

When it happens

Trigger: `validate` -> `validate_data_type_compatibility`: e.g. RW `Int32` column vs downstream `nvarchar`, RW `Varchar` vs `int`, RW `Decimal` vs `float`, RW `Boolean` vs `int`, etc. — any pair the compatibility matrix rejects.

Common situations: Downstream table created with different types than the RW schema; user altered one side after sink creation; copy-pasted DDL where `BIGINT` became `INT`; RW migrations changed a column type while downstream stayed fixed.

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

Appendix: source

Thrown at src/connector/src/sink/sqlserver.rs:957

    }
}

fn normalize_sql_server_column_name(column_name: &str) -> String {
    // SQL Server identifiers are usually case-insensitive depending on database collation.
    // Match metadata by a case-insensitive key so validation follows that common behavior.
    column_name.to_lowercase()
}

fn validate_data_type_compatibility(
    column_name: &str,
    rw_data_type: &DataType,
    sql_server_data_type: &str,
) -> Result<()> {
    if sql_server_data_type_is_compatible(rw_data_type, sql_server_data_type) {
        return Ok(());
    }

    Err(SinkError::SqlServer(anyhow!(format!(
        "column {} data type {:?} is incompatible with downstream SQL Server type {}",
        column_name, rw_data_type, sql_server_data_type
    ))))
}

fn sql_server_data_type_is_compatible(rw_data_type: &DataType, sql_server_data_type: &str) -> bool {
    match rw_data_type {
        DataType::Boolean => sql_server_data_type == "bit",
        DataType::Int16 => matches!(sql_server_data_type, "smallint" | "int" | "bigint"),
        DataType::Int32 => matches!(sql_server_data_type, "int" | "bigint"),
        DataType::Int64 => sql_server_data_type == "bigint",
        DataType::Float32 => matches!(sql_server_data_type, "real" | "float"),
        DataType::Float64 => sql_server_data_type == "float",
        DataType::Decimal => matches!(sql_server_data_type, "decimal" | "numeric"),
        DataType::Date => sql_server_data_type == "date",
        DataType::Varchar => matches!(
            sql_server_data_type,
            "char" | "nchar" | "varchar" | "nvarchar" | "text" | "ntext"

View on GitHub (pinned to 6469eb736d)