risingwavelabs/risingwave · error

Invalid order key item `{item}`: `NULLS` must be followed by

Error message

Invalid order key item `{item}`: `NULLS` must be followed by `FIRST` or `LAST`

What it means

This error is thrown by `parse_order_key_exprs` when an order key item contains the keyword `NULLS` but there is no following token (end of the item string). The parser expects `NULLS` to be immediately followed by `FIRST` or `LAST` to determine null ordering for the Iceberg sort order; a dangling `NULLS` is a syntax error.

Source

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

            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() {
            match tokens[idx].to_ascii_lowercase().as_str() {
                "asc" => {
                    direction = SortDirection::Ascending;
                    idx += 1;
                }
                "desc" => {
                    direction = SortDirection::Descending;
                    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]`"
                    );
                }
            }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Append `FIRST` or `LAST` after `NULLS` in the order key item, e.g. `col asc nulls first`
  2. Remove the dangling `NULLS` keyword if default null ordering is acceptable
  3. Verify the full order_key string follows `column [asc|desc] [nulls first|last]`

Example fix

// before
order_key = 'ts asc nulls'
// after
order_key = 'ts asc nulls first'
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_order_key(item: &str) -> bool {
    let toks: Vec<&str> = item.split_whitespace().collect();
    match toks.as_slice() {
        [_] => true,
        [_, d] => matches!(d.to_ascii_lowercase().as_str(), "asc" | "desc"),
        [_, d, "nulls", o] if matches!(o.to_ascii_lowercase().as_str(), "first" | "last") => {
            matches!(d.to_ascii_lowercase().as_str(), "asc" | "desc")
        }
        _ => false,
    }
}
assert!(order_key.split(',').all(|i| is_valid_order_key(i.trim())));

Try / catch

match parse_order_key_exprs(item) {
    Ok(keys) => keys,
    Err(e) if e.to_string().contains("NULLS") => {
        // fix or drop the NULLS clause, then retry
        eprintln!("fix NULLS clause: {e}");
        Default::default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling the Iceberg sink `order_key` option with an item such as `col asc nulls` (trailing `nulls` with nothing after it) or `col nulls` with no null-order word; typically a typo or a truncated config value.

Common situations: Hand-editing connector options in a CREATE SINK statement or a TOML/CLI config and truncating the value; copy-pasting a partially written sort spec; forgetting `FIRST`/`LAST` after adding `NULLS`.

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