{"record":{"id":"bac6054ece19134a","repo":"risingwavelabs/risingwave","slug":"invalid-order-key-empty-item-in-expr","errorCode":null,"errorMessage":"Invalid order key: empty item in `{expr}`","messagePattern":"Invalid order key: empty item in `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/create_table.rs","lineNumber":487,"sourceCode":"                Transform::from_str(&func)\n                    .with_context(|| format!(\"invalid transform function {}\", func))?,\n            )\n        };\n        partition_columns.push((column.to_owned(), transform));\n    }\n    Ok(partition_columns)\n}\n\npub fn parse_order_key_exprs(\n    expr: String,\n) -> std::result::Result<Vec<IcebergOrderKeyField>, anyhow::Error> {\n    let mut order_keys = Vec::new();\n    let mut seen_columns = std::collections::HashSet::new();\n\n    for raw_item in expr.split(',') {\n        let item = raw_item.trim();\n        if item.is_empty() {\n            bail!(\"Invalid order key: empty item in `{expr}`\");\n        }\n\n        let tokens = item.split_whitespace().collect_vec();\n        if tokens.is_empty() {\n            bail!(\"Invalid order key item `{item}`\");\n        }\n        if tokens.len() > 4 {\n            bail!(\n                \"Invalid order key item `{item}`\\nHINT: Supported format is `column [asc|desc] [nulls first|last]`\"\n            );\n        }\n\n        let column = tokens[0];\n        if !ORDER_KEY_COLUMN_RE.is_match(column) {\n            bail!(\n                \"Invalid order key column `{column}`\\nHINT: Only plain column names are supported in order_key\"\n            );\n        }","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/create_table.rs#L469-L505","documentation":"parse_order_key_exprs splits the order_key option string on commas and parses each item. An empty item means a bare or doubled comma (or a trailing/leading comma) was found, so the parser cannot derive a sort column for that position. It is thrown to surface a malformed order_key specification early, before an Iceberg table is created with a bad sort spec.","triggerScenarios":"Calling validate_order_key_columns (via iceberg sink table creation) with an order_key string containing an empty element after comma splitting, e.g. `a,,b`, `a,`, `,a`, or order_key=`\"\"`/`,`.","commonSituations":"Hand-written DDL with a trailing comma after the last column; programmatically joined column lists where a list element is empty; copy-pasted options with double commas; templated SQL where a variable evaluates to empty.","solutions":["Remove the empty item: no leading, trailing, or doubled commas in order_key","If a column variable is empty at runtime, fix the variable or drop the item before joining","Print the raw expr (it is embedded in the message) and delete the offending comma","If dynamic ordering is optional, pass no order_key rather than an empty string"],"exampleFix":"// before\nWITH ( connector = 'iceberg', order_key = 'id, name,' )\n// after\nWITH ( connector = 'iceberg', order_key = 'id, name' )","handlingStrategy":"validation","validationCode":"let expr = \"id, name\"; // user-supplied order_key\nlet items: Vec<&str> = expr.split(',').map(|s| s.trim()).collect();\nif items.iter().any(|i| i.is_empty()) {\n    return Err(format!(\"order_key `{expr}` has an empty item; remove doubled/trailing commas\"));\n}","typeGuard":"fn has_empty_order_key_item(expr: &str) -> bool {\n    expr.split(',').any(|item| item.trim().is_empty())\n}","tryCatchPattern":null,"preventionTips":["Never end an order_key list with a comma","Build order_key by joining a non-empty list: cols.join(\",\")","Reject empty strings before setting the option — pass no order_key if you have nothing","Add a config linter that splits on ',' and asserts no blank items"],"tags":["validation","iceberg","config","sql"],"backgroundTag":"invalid-argument-format","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"}