{"record":{"id":"56b80a309c7c01bb","repo":"risingwavelabs/risingwave","slug":"invalid-iceberg-table-identifier-identifier","errorCode":null,"errorMessage":"Invalid iceberg table identifier '{}': identifier parts must not be empty","messagePattern":"Invalid iceberg table identifier '(.+?)': identifier parts must not be empty","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/connector/src/connector_common/iceberg/mod.rs","lineNumber":270,"sourceCode":"\nimpl IcebergTableIdentifier {\n    pub fn database_name(&self) -> Option<&str> {\n        self.database_name.as_deref()\n    }\n\n    pub fn table_name(&self) -> &str {\n        &self.table_name\n    }\n\n    fn identifier_parts(&self) -> ConnectorResult<Vec<&str>> {\n        let mut parts = Vec::new();\n        if let Some(database_name) = &self.database_name {\n            parts.extend(database_name.split('.'));\n        }\n        parts.extend(self.table_name.split('.'));\n\n        if parts.iter().any(|part| part.is_empty()) {\n            bail!(\n                \"Invalid iceberg table identifier '{}': identifier parts must not be empty\",\n                self.full_identifier()\n            );\n        }\n\n        Ok(parts)\n    }\n\n    fn full_identifier(&self) -> String {\n        match &self.database_name {\n            Some(database_name) => format!(\"{}.{}\", database_name, self.table_name),\n            None => self.table_name.clone(),\n        }\n    }\n\n    pub fn to_table_ident(&self) -> ConnectorResult<TableIdent> {\n        let ret = TableIdent::from_strs(self.identifier_parts()?);\n","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/connector_common/iceberg/mod.rs#L252-L288","documentation":"The Iceberg table identifier built from `database_name` and `table_name` with-properties produced an empty part after splitting on '.'. The connector refuses identifiers whose namespace or table segment is empty because Iceberg catalogs require non-empty identifier components. `full_identifier()` echoes the offending value so the developer can see what was parsed.","triggerScenarios":"Calling `identifier_parts` (via `to_table_ident` or `validate`) with `table_name` set to \"\", starting/ending with '.', containing consecutive dots, or a `database_name` that is empty or has empty segments (e.g. \"a..b\", \".tbl\", \"db.\").","commonSituations":"Users writing `create table ... with (table.name = '')` or `database.name = 'db.'`; template/variable interpolation leaving a placeholder empty; copy-paste of dotted identifiers from another system with trailing separators.","solutions":["Set a non-empty `table.name` property with no leading/trailing/embedded dots.","If `database.name` is supplied, ensure it is non-empty and each dot-separated segment is non-empty.","Check upstream variable substitution or SQL generation that may inject an empty value."],"exampleFix":"// before\ncreate table t with (\n  connector = 'iceberg',\n  database.name = 'db.',\n  table.name = 'events'\n);\n// after\ncreate table t with (\n  connector = 'iceberg',\n  database.name = 'db',\n  table.name = 'events'\n);","handlingStrategy":"validation","validationCode":"function validateIcebergIdentifier(db, table) {\n  const parts = [...(db ?? '').split('.'), ...table.split('.')];\n  if (parts.some(p => p.length === 0)) {\n    throw new Error(`Invalid iceberg identifier: ${db ? db + '.' : ''}${table}`);\n  }\n}","typeGuard":"const isValidIdentifier = (s) => typeof s === 'string' && s.split('.').every(p => p.length > 0);","tryCatchPattern":null,"preventionTips":["Trim identifiers and reject empty strings at config load time.","Never build identifiers by naive string concatenation with dots from user input.","Add a CI/unit test covering dotted-identifier parsing edge cases."],"tags":["iceberg","config-validation","identifier"],"backgroundTag":"invalid-identifier-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}