{"record":{"id":"73f93f65df4246f5","repo":"risingwavelabs/risingwave","slug":"column-order-mismatch-at-position-the-sink-has","errorCode":null,"errorMessage":"Column order mismatch at position {}: the sink has column `{}` but the Iceberg table has column `{}`. The Iceberg sink maps columns to the table by position, so the sink's column order must match the Iceberg table columns [{}].","messagePattern":"Column order mismatch at position (.+?): the sink has column `(.+?)` but the Iceberg table has column `(.+?)`\\. The Iceberg sink maps columns to the table by position, so the sink's column order must match the Iceberg table columns \\[(.+?)\\]\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/create_table.rs","lineNumber":424,"sourceCode":"    let mut schema_fields = HashMap::new();\n    rw_schema.fields.iter().for_each(|field| {\n        let res = schema_fields.insert(field.name.as_str(), &field.data_type);\n        // This assert is to make sure there is no duplicate field name in the schema.\n        assert!(res.is_none())\n    });\n\n    check_compatibility(schema_fields, &arrow_schema.fields)?;\n\n    // The sink writes columns to the Iceberg table by position, so the column order\n    // must match. The check above only validates the name set and types.\n    for (idx, (rw_field, arrow_field)) in rw_schema\n        .fields\n        .iter()\n        .zip_eq_fast(arrow_schema.fields().iter())\n        .enumerate()\n    {\n        if rw_field.name.as_str() != arrow_field.name().as_str() {\n            bail!(\n                \"Column order mismatch at position {}: the sink has column `{}` but the \\\n                 Iceberg table has column `{}`. The Iceberg sink maps columns to the table \\\n                 by position, so the sink's column order must match the Iceberg table \\\n                 columns [{}].\",\n                idx,\n                rw_field.name,\n                arrow_field.name(),\n                arrow_schema.fields().iter().map(|f| f.name()).join(\", \"),\n            );\n        }\n    }\n\n    Ok(())\n}\n\npub fn parse_partition_by_exprs(\n    expr: String,\n) -> std::result::Result<Vec<(String, Transform)>, anyhow::Error> {","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/create_table.rs#L406-L442","documentation":"The Iceberg sink writes columns to the table by position, so `try_matches_arrow_schema` zips RW and Iceberg fields and requires names to match at each index. If positionally aligned columns have different names, it bails with a detailed message listing the position, both column names, and the full Iceberg column list.","triggerScenarios":"Called from `create_and_validate_table_impl`: e.g., sink schema is (a, b) but Iceberg table is (b, a) — same set, wrong order.","commonSituations":"Sink query column order differs from the table's column order; Iceberg table was created from a different column order or evolved by inserting a column; renaming a column in the table externally.","solutions":["Reorder the sink query's SELECT list to exactly match the Iceberg table's column order.","Recreate the sink (or the table) so both schemas are generated in the same order.","Check the full printed Iceberg column list in the message and align one-to-one positionally."],"exampleFix":"// before: table is (a, b), sink selects (b, a)\nCREATE SINK s AS SELECT b, a FROM t;\n// after\nCREATE SINK s AS SELECT a, b FROM t;","handlingStrategy":"validation","validationCode":"// verify positional names match before creating\nfor (i, (rw, arrow)) in rw_schema.fields.iter().zip(arrow_schema.fields()).enumerate() {\n    if rw.name != arrow.name() {\n        eprintln!(\"position {i}: sink `{}` vs table `{}`\", rw.name, arrow.name());\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Order the sink SELECT list to mirror the Iceberg table's column order exactly.","Avoid inserting columns into existing Iceberg tables that sinks write to; add columns at the end and recreate the sink.","Treat the Iceberg table DDL as the source of truth for the sink projection."],"tags":["iceberg","schema","column-order","compatibility"],"backgroundTag":"shape-mismatch","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}