{"record":{"id":"7a9c5743e48fd42b","repo":"risingwavelabs/risingwave","slug":"failed-to-add-partition-columns","errorCode":null,"errorMessage":"failed to add partition columns","messagePattern":"failed to add partition columns","errorType":"exception","errorClass":"SinkError::Iceberg","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/create_table.rs","lineNumber":206,"sourceCode":"                    Some(id) => partition_fields.push(\n                        UnboundPartitionField::builder()\n                            .source_id(id)\n                            .transform(transform)\n                            .name(format!(\"_p_{}\", column))\n                            .field_id(PARTITION_DATA_ID_START + i as i32)\n                            .build(),\n                    ),\n                    None => bail!(format!(\n                        \"Partition source column does not exist in schema: {}\",\n                        column\n                    )),\n                };\n            }\n            Some(\n                UnboundPartitionSpec::builder()\n                    .with_spec_id(0)\n                    .add_partition_fields(partition_fields)\n                    .map_err(|e| SinkError::Iceberg(anyhow!(e)))\n                    .context(\"failed to add partition columns\")?\n                    .build(),\n            )\n        }\n        None => None,\n    };\n\n    let sort_order = match &config.order_key {\n        Some(order_key) => Some(build_sort_order(order_key, &iceberg_schema)?),\n        None => None,\n    };\n\n    // Some JNI catalogs extract `format-version` from table properties, while\n    // native Rust Glue rejects reserved properties before creating metadata.\n    let properties = if matches!(\n        config.catalog_kind()?,\n        IcebergCatalogKind::Glue(IcebergCatalogRuntime::NativeRust)\n    ) {","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/create_table.rs#L188-L224","documentation":"After building the partition field descriptors, they are attached to an UnboundPartitionSpec via add_partition_fields. If the iceberg crate rejects any field (invalid transform for the source type, duplicate names/ids, conflicting field ids), the error is wrapped with this static context message.","triggerScenarios":"create_table_if_not_exists_impl calls UnboundPartitionSpec::builder().with_spec_id(0).add_partition_fields(partition_fields) and it returns Err — typically a transform not applicable to the column's type (e.g. year/month/day on a non-date/timestamp column, bucket on unsupported types) or an invalid field id assignment.","commonSituations":"Partition transform (year/month/day/hour/truncate/bucket) applied to a column type it doesn't support; partitioning on VARCHAR with a temporal transform; multiple partition fields colliding on generated names (_p_<column>).","solutions":["Read the chained underlying error to see which partition field was rejected.","Match the transform to the column type (e.g. use `day` only on date/timestamp columns, `truncate`/`bucket` on appropriate types).","Fix the partition config in the sink WITH options and recreate the sink.","Check for duplicate partition column names."],"exampleFix":"// before\nWITH (connector='iceberg', partition.by='day(user_name)') -- day() on a VARCHAR\n// after\nWITH (connector='iceberg', partition.by='truncate(user_name, 10)')\n-- or partition by a timestamp column: partition.by='day(event_time)'","handlingStrategy":"validation","validationCode":"// Check each partition transform is valid for its column type before creating\n// e.g. day/month/year only on date/timestamp; truncate/bucket per iceberg rules\nfor (col, transform) in partition_specs {\n    if !transform_supports(transform, type_of(col)) {\n        eprintln!(\"transform {transform} unsupported for column {col} type\");\n    }\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"failed to add partition columns\") => {\n        // fix transform/column pairing in partition.by, then recreate the sink\n    }\n    other => other?,\n}","preventionTips":["Apply temporal transforms only to date/timestamp columns.","Use truncate/bucket transforms appropriate to the column type.","Avoid duplicate partition column names (each gets a _p_<name> field).","Consult Iceberg partition transform rules when writing partition.by."],"tags":["rust","iceberg","partition","transform"],"backgroundTag":"invalid-argument-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}