{"record":{"id":"f092d17a845768c6","repo":"risingwavelabs/risingwave","slug":"system-column-is-not-allowed-in-order-key","errorCode":null,"errorMessage":"System column `{}` is not allowed in order_key","messagePattern":"System column `(.+?)` is not allowed in order_key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/create_table.rs","lineNumber":572,"sourceCode":"    if order_keys.is_empty() {\n        bail!(\"order_key must not be empty\");\n    }\n\n    Ok(order_keys)\n}\n\npub fn validate_order_key_columns<'a>(\n    order_key: &str,\n    columns: impl IntoIterator<Item = &'a str>,\n) -> std::result::Result<Vec<IcebergOrderKeyField>, anyhow::Error> {\n    let parsed = parse_order_key_exprs(order_key.to_owned())?;\n    let columns = columns\n        .into_iter()\n        .map(|column| column.to_ascii_lowercase())\n        .collect::<std::collections::HashSet<_>>();\n    for item in &parsed {\n        if item.column.starts_with('_') {\n            bail!(\n                \"System column `{}` is not allowed in order_key\",\n                item.column\n            );\n        }\n        if !columns.contains(&item.column.to_ascii_lowercase()) {\n            bail!(\"Order key column does not exist in schema: {}\", item.column);\n        }\n    }\n    Ok(parsed)\n}\n\nfn build_sort_order(order_key: &str, schema: &iceberg::spec::Schema) -> Result<SortOrder> {\n    let order_fields = validate_order_key_columns(\n        order_key,\n        schema\n            .as_struct()\n            .fields()\n            .iter()","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/create_table.rs#L554-L590","documentation":"`validate_order_key_columns` rejects order key items whose column name starts with an underscore (`_`), since those are RisingWave system/hidden columns that have no counterpart in the Iceberg table schema. Only user-defined columns may be used in the sort order.","triggerScenarios":"Including a system column such as `_row_id` or `_rw_ts` in the Iceberg sink `order_key` option, e.g. `order_key = '_row_id'` — the check runs after parsing, during `build_sort_order`/sink option construction.","commonSituations":"Users familiar with RisingWave internal columns trying to sort by them in Iceberg sinks; accidentally prefixing a column with `_`; scripts generating keys from internal metadata.","solutions":["Replace the system column with a real user-defined column from the sink schema","Remove the `_`-prefixed item from order_key","Pick a physical column that exists in the Iceberg table (the next check also verifies existence)"],"exampleFix":"// before\norder_key = '_row_id'\n// after\norder_key = 'id'","handlingStrategy":"validation","validationCode":"fn uses_system_columns(order_key: &str) -> bool {\n    order_key.split(',').any(|i| {\n        i.trim().split_whitespace().next()\n            .map_or(false, |c| c.starts_with('_'))\n    })\n}\nassert!(!uses_system_columns(order_key), \"system columns (_*) are not allowed in order_key\");","typeGuard":null,"tryCatchPattern":"match build_sort_order(order_key, &columns) {\n    Ok(sort) => sort,\n    Err(e) if e.to_string().contains(\"System column\") => {\n        eprintln!(\"replace _-prefixed column with a user column: {e}\");\n        Default::default()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never reference `_`-prefixed columns in sink options; they exist only inside RisingWave","Cross-check order key names against the sink schema's user-defined columns","Filter generated keys to columns present in the Iceberg table schema before configuring the sink"],"tags":["rust","validation","iceberg","sink","system-columns"],"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-14T16:17:12.679Z"}