risingwavelabs/risingwave · error

Invalid order key token `{token}` in `{item}` HINT: Supporte

Error message

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

What it means

Thrown by `parse_order_key_exprs` as the catch-all branch when a token in an order key item matches none of the recognized keywords (`asc`, `desc`, `nulls`). The grammar for each item is `column [asc|desc] [nulls first|last]`, so any unexpected extra or misspelled token is rejected with a HINT showing the supported format.

Source

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

                    idx += 1;
                }
                "nulls" => {
                    let order = tokens.get(idx + 1).ok_or_else(|| {
                        anyhow!(
                            "Invalid order key item `{item}`: `NULLS` must be followed by `FIRST` or `LAST`"
                        )
                    })?;
                    null_order = Some(match order.to_ascii_lowercase().as_str() {
                        "first" => NullOrder::First,
                        "last" => NullOrder::Last,
                        _ => bail!(
                            "Invalid order key item `{item}`\nHINT: `NULLS` must be followed by `FIRST` or `LAST`"
                        ),
                    });
                    idx += 2;
                }
                token => {
                    bail!(
                        "Invalid order key token `{token}` in `{item}`\nHINT: Supported format is `column [asc|desc] [nulls first|last]`"
                    );
                }
            }
        }

        order_keys.push(IcebergOrderKeyField {
            column: column.to_owned(),
            direction,
            null_order: null_order
                .unwrap_or_else(|| IcebergOrderKeyField::default_null_order(direction)),
        });
    }

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

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Rewrite the item to `column [asc|desc] [nulls first|last]`, e.g. `ts desc nulls last`
  2. Remove unsupported tokens (COLLATE, expressions, functions) — only plain column names are allowed
  3. Split multiple columns into a comma-separated list of items, each following the supported format

Example fix

// before
order_key = 'lower(name) asc, ts asec'
// after
order_key = 'name asc, ts desc nulls last'
Defensive patterns

Strategy: validation

Validate before calling

fn item_matches_grammar(item: &str) -> bool {
    let toks: Vec<&str> = item.split_whitespace().collect();
    let dir_ok = |t: Option<&&str>| t.map_or(true, |d| matches!(*d, "asc" | "desc" | "ASC" | "DESC"));
    let is_ident = |t: &str| !t.is_empty() && t.chars().all(|c| c.is_alphanumeric() || c == '_');
    match toks.as_slice() {
        [c] if is_ident(c) => true,
        [c, d] if is_ident(c) && dir_ok(Some(&d)) => true,
        [c, d, "nulls", o] if is_ident(c) && dir_ok(Some(&d)) && matches!(*o, "first" | "last" | "FIRST" | "LAST") => true,
        _ => false,
    }
}
assert!(order_key.split(',').all(|i| item_matches_grammar(i.trim())));

Try / catch

match parse_order_key_exprs(item) {
    Ok(keys) => keys,
    Err(e) if e.to_string().contains("Supported format is") => {
        eprintln!("normalize item to `column [asc|desc] [nulls first|last]`: {e}");
        Default::default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing items with unsupported syntax such as `col asc collate x`, `col asc nulls`, direction typos like `col asec`, extra separators like `col!`, or multi-word garbage in the Iceberg sink `order_key` option.

Common situations: Copying PostgreSQL-style ORDER BY clauses with constructs (COLLATE, arithmetic, functions) unsupported by the Iceberg sort-order mini-grammar; typos in `asc`/`desc`; stray commas or whitespace inside a quoted item.

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/37c66209f1f8098c. Report an issue: GitHub.