risingwavelabs/risingwave · error

order_key must not be empty

Error message

order_key must not be empty

What it means

After parsing all comma-separated items, `parse_order_key_exprs` rejects an empty result: an Iceberg sort order requires at least one order key. An empty or whitespace-only `order_key` option yields no parsed keys and is treated as invalid rather than silently producing an unsorted table.

Source

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

                }
                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");
    }

    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",

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Provide at least one column in order_key, e.g. `order_key = 'ts'`
  2. Remove/unset the order_key option entirely if no sort order is desired (if the API permits)
  3. Check templating/variable expansion so the key is not interpolated to an empty string

Example fix

// before
order_key = ''
// after
order_key = 'event_time desc nulls last'
Defensive patterns

Strategy: validation

Validate before calling

let trimmed = order_key.trim();
if trimmed.is_empty() || trimmed.split(',').all(|i| i.trim().is_empty()) {
    // unset the option or provide a real key
}
assert!(!order_key.trim().is_empty(), "order_key must contain at least one column");

Try / catch

match parse_order_key_exprs(order_key) {
    Ok(keys) if keys.is_empty() => eprintln!("order_key empty; provide at least one column"),
    Ok(keys) => keys,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Setting the Iceberg sink `order_key` option to an empty string (`''`), only commas (`',,,'`), or whitespace (`' '`); also passing items that are all empty after trimming.

Common situations: Templated config where the order key variable is unset/empty; removing the only column from the key without unsetting the option; YAML/TOML keys left as empty values.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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