{"record":{"id":"144d7efdc83cd1b5","repo":"risingwavelabs/risingwave","slug":"invalid-order-key-item-item-hint-nulls-must","errorCode":null,"errorMessage":"Invalid order key item `{item}`\nHINT: `NULLS` must be followed by `FIRST` or `LAST`","messagePattern":"Invalid order key item `(.+?)`\nHINT: `NULLS` must be followed by `FIRST` or `LAST`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/create_table.rs","lineNumber":532,"sourceCode":"            match tokens[idx].to_ascii_lowercase().as_str() {\n                \"asc\" => {\n                    direction = SortDirection::Ascending;\n                    idx += 1;\n                }\n                \"desc\" => {\n                    direction = SortDirection::Descending;\n                    idx += 1;\n                }\n                \"nulls\" => {\n                    let order = tokens.get(idx + 1).ok_or_else(|| {\n                        anyhow!(\n                            \"Invalid order key item `{item}`: `NULLS` must be followed by `FIRST` or `LAST`\"\n                        )\n                    })?;\n                    null_order = Some(match order.to_ascii_lowercase().as_str() {\n                        \"first\" => NullOrder::First,\n                        \"last\" => NullOrder::Last,\n                        _ => bail!(\n                            \"Invalid order key item `{item}`\\nHINT: `NULLS` must be followed by `FIRST` or `LAST`\"\n                        ),\n                    });\n                    idx += 2;\n                }\n                token => {\n                    bail!(\n                        \"Invalid order key token `{token}` in `{item}`\\nHINT: Supported format is `column [asc|desc] [nulls first|last]`\"\n                    );\n                }\n            }\n        }\n\n        order_keys.push(IcebergOrderKeyField {\n            column: column.to_owned(),\n            direction,\n            null_order: null_order\n                .unwrap_or_else(|| IcebergOrderKeyField::default_null_order(direction)),","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/create_table.rs#L514-L550","documentation":"Thrown by `parse_order_key_exprs` when the token after `NULLS` is not `FIRST` or `LAST` (case-insensitive). The parser only accepts those two values for null ordering and rejects any other word with this message.","triggerScenarios":"Passing an order key item like `col asc nulls ignore` or `col nulls firts` (misspelled) in the Iceberg sink `order_key` option — `NULLS` is present and followed by a token, but the token is not `FIRST`/`LAST`.","commonSituations":"Typos such as `nulls NLast`, using other SQL dialects' null-ordering words, or confusing `NULLS FIRST` with `NULLSFIRST`-style compact syntax in the config.","solutions":["Replace the token after `NULLS` with exactly `FIRST` or `LAST` (any case)","Remove the `NULLS ...` clause entirely to use the default null order for the direction","Check the item for stray characters or split words, e.g. `nulls firstt`"],"exampleFix":"// before\norder_key = 'ts desc nulls top'\n// after\norder_key = 'ts desc nulls last'","handlingStrategy":"validation","validationCode":"fn valid_null_order(item: &str) -> bool {\n    let toks: Vec<&str> = item.to_ascii_lowercase().split_whitespace().collect();\n    !toks.windows(2).any(|w| w[0] == \"nulls\" && !matches!(w[1], \"first\" | \"last\"))\n}\nassert!(order_key.split(',').all(|i| valid_null_order(i.trim())));","typeGuard":null,"tryCatchPattern":"match parse_order_key_exprs(item) {\n    Ok(keys) => keys,\n    Err(e) if e.to_string().contains(\"HINT: `NULLS`\") => {\n        eprintln!(\"use FIRST or LAST after NULLS: {e}\");\n        Default::default()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Spell null ordering as exactly `nulls first` or `nulls last` (any case)","Do not import null-ordering syntax from other SQL dialects","Keep each order key item simple: column, optional direction, optional nulls clause"],"tags":["rust","parsing","iceberg","sink"],"backgroundTag":"invalid-enum-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}