risingwavelabs/risingwave · error

System column `{}` is not allowed in order_key

Error message

System column `{}` is not allowed in order_key

What it means

`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.

Source

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

    if order_keys.is_empty() {
        bail!("order_key must not be empty");
    }

    Ok(order_keys)
}

pub fn validate_order_key_columns<'a>(
    order_key: &str,
    columns: impl IntoIterator<Item = &'a str>,
) -> std::result::Result<Vec<IcebergOrderKeyField>, anyhow::Error> {
    let parsed = parse_order_key_exprs(order_key.to_owned())?;
    let columns = columns
        .into_iter()
        .map(|column| column.to_ascii_lowercase())
        .collect::<std::collections::HashSet<_>>();
    for item in &parsed {
        if item.column.starts_with('_') {
            bail!(
                "System column `{}` is not allowed in order_key",
                item.column
            );
        }
        if !columns.contains(&item.column.to_ascii_lowercase()) {
            bail!("Order key column does not exist in schema: {}", item.column);
        }
    }
    Ok(parsed)
}

fn build_sort_order(order_key: &str, schema: &iceberg::spec::Schema) -> Result<SortOrder> {
    let order_fields = validate_order_key_columns(
        order_key,
        schema
            .as_struct()
            .fields()
            .iter()

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Replace the system column with a real user-defined column from the sink schema
  2. Remove the `_`-prefixed item from order_key
  3. Pick a physical column that exists in the Iceberg table (the next check also verifies existence)

Example fix

// before
order_key = '_row_id'
// after
order_key = 'id'
Defensive patterns

Strategy: validation

Validate before calling

fn uses_system_columns(order_key: &str) -> bool {
    order_key.split(',').any(|i| {
        i.trim().split_whitespace().next()
            .map_or(false, |c| c.starts_with('_'))
    })
}
assert!(!uses_system_columns(order_key), "system columns (_*) are not allowed in order_key");

Try / catch

match build_sort_order(order_key, &columns) {
    Ok(sort) => sort,
    Err(e) if e.to_string().contains("System column") => {
        eprintln!("replace _-prefixed column with a user column: {e}");
        Default::default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/f092d17a845768c6. Report an issue: GitHub.