risingwavelabs/risingwave · error

Invalid order key item `{item}` HINT: Supported format is `c

Error message

Invalid order key item `{item}`
HINT: Supported format is `column [asc|desc] [nulls first|last]`

What it means

Each order key item may contain at most 4 whitespace-separated tokens: `column [asc|desc] [nulls first|last]`. A longer token list means the item mixes in unsupported extra words (functions, expressions, multiple columns in one item). The HINT in the message documents the accepted grammar.

Source

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

pub fn parse_order_key_exprs(
    expr: String,
) -> std::result::Result<Vec<IcebergOrderKeyField>, anyhow::Error> {
    let mut order_keys = Vec::new();
    let mut seen_columns = std::collections::HashSet::new();

    for raw_item in expr.split(',') {
        let item = raw_item.trim();
        if item.is_empty() {
            bail!("Invalid order key: empty item in `{expr}`");
        }

        let tokens = item.split_whitespace().collect_vec();
        if tokens.is_empty() {
            bail!("Invalid order key item `{item}`");
        }
        if tokens.len() > 4 {
            bail!(
                "Invalid order key item `{item}`\nHINT: Supported format is `column [asc|desc] [nulls first|last]`"
            );
        }

        let column = tokens[0];
        if !ORDER_KEY_COLUMN_RE.is_match(column) {
            bail!(
                "Invalid order key column `{column}`\nHINT: Only plain column names are supported in order_key"
            );
        }
        if !seen_columns.insert(column.to_ascii_lowercase()) {
            bail!("Duplicate column `{column}` in order_key");
        }

        let mut direction = SortDirection::Ascending;
        let mut null_order = None;
        let mut idx = 1;
        while idx < tokens.len() {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Use only plain column names, one item per column separated by commas
  2. Convert expressions to separate computed columns in the table and reference those columns
  3. Add the missing comma between column names (e.g. `id,name` not `id name`)
  4. Keep optional keywords to at most two: a direction (asc/desc) and a nulls placement (nulls first/last)

Example fix

// before
order_key = 'date_trunc(day, event_time) desc'
// after
order_key = 'event_day desc'  -- event_day is a materialized column
Defensive patterns

Strategy: validation

Validate before calling

fn order_key_item_token_count_ok(item: &str) -> bool {
    matches!(item.split_whitespace().count(), 1..=4)
}

Type guard

fn is_simple_order_key_item(item: &str) -> bool {
    let toks: Vec<&str> = item.split_whitespace().collect();
    (1..=4).contains(&toks.len())
}

Prevention

When it happens

Trigger: order_key items like `date_trunc('day', ts)`, `a b c d e`, `id asc nulls first extra`, or comma-separated columns mistakenly written as space-separated (`id name`) instead of `id,name`.

Common situations: Trying to use expressions/functions in order_key (only plain column names are supported); forgetting the comma between two columns so they parse as one item; pasting a full ORDER BY clause from SQL.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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