risingwavelabs/risingwave · error
Invalid order key column `{column}` HINT: Only plain column
Error message
Invalid order key column `{column}`
HINT: Only plain column names are supported in order_key What it means
The first token of each order key item must match ORDER_KEY_COLUMN_RE, a pattern that accepts only plain SQL column identifiers. Quoted identifiers, qualified names like t.col, function calls, or other expression forms are rejected because the Iceberg sink order_key maps 1:1 onto table columns.
Source
Thrown at src/connector/src/sink/iceberg/create_table.rs:502
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() {
match tokens[idx].to_ascii_lowercase().as_str() {
"asc" => {
direction = SortDirection::Ascending;
idx += 1;
}
"desc" => {
direction = SortDirection::Descending;View on GitHub (pinned to 6469eb736d)
Solutions
- Use the bare, unquoted column name exactly as declared (e.g. `id`, not `t.id` or `\"id\"`)
- Rename columns with special characters/spaces, or add clean alias columns
- Move any computed value into a real table column and reference that column in order_key
- Validate each item against the regex ^[A-Za-z_][A-Za-z0-9_]*$-style identifier before configuring
Example fix
// before order_key = 't.event_time desc' // after order_key = 'event_time desc'
Defensive patterns
Strategy: validation
Validate before calling
let column_re = regex::Regex::new(r"^[A-Za-z_][A-Za-z0-9_]*$").unwrap();
for item in expr.split(',').map(|s| s.trim()) {
let col = item.split_whitespace().next().unwrap_or("");
if !column_re.is_match(col) {
return Err(format!("order_key column `{col}` must be a plain identifier"));
}
} Type guard
fn is_plain_identifier(column: &str) -> bool {
!column.is_empty()
&& column.chars().next().map_or(false, |c| c.is_ascii_alphabetic() || c == '_')
&& column.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
} Prevention
- Use bare column names — no quoting, no schema/table qualification
- Rename or alias columns containing spaces or special characters
- Look up the exact column names in the created table before writing order_key
- Mirror the parser's regex check in your config pipeline
When it happens
Trigger: order_key items such as `\"user id\"` (quoted), `t.id` (qualified), `count(*)`, `col + 1`, or identifiers starting with a digit/special char that fail the regex.
Common situations: Copying an ORDER BY expression from a query into order_key; qualifying column names out of habit; spaces inside a column name without knowing quoting is unsupported in this option.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Invalid order key: empty item in `{expr}`
- Invalid order key item `{item}`
- Invalid order key item `{item}` HINT: Supported format is `c
- `warehouse.path` must be set
- Unsupported scheme: {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/8445e842c7e226ea.
Report an issue: GitHub.