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
- Rewrite the item to `column [asc|desc] [nulls first|last]`, e.g. `ts desc nulls last`
- Remove unsupported tokens (COLLATE, expressions, functions) — only plain column names are allowed
- 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
- Read the HINT in the message: only `column [asc|desc] [nulls first|last]` is supported
- Strip SQL-only clauses (COLLATE, expressions) before passing order keys
- Run a dry parse of order_key strings in config tests
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
- Invalid order key item `{item}`: `NULLS` must be followed by
- Invalid order key item `{item}` HINT: `NULLS` must be follow
- iceberg sink: schema evolution not supported; expect schema
- iceberg sink: partition evolution not supported; expect part
- order_key must not be empty
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/37c66209f1f8098c.
Report an issue: GitHub.