{"record":{"id":"666cb9e718e3ab99","repo":"risingwavelabs/risingwave","slug":"failed-to-create-iceberg-table-666cb9","errorCode":null,"errorMessage":"failed to create iceberg table","messagePattern":"failed to create iceberg table","errorType":"exception","errorClass":"SinkError::Iceberg","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/create_table.rs","lineNumber":268,"sourceCode":"            .location(location)\n            .sort_order(sort_order)\n            .build(),\n        (Some(location), None, None) => table_creation_builder.location(location).build(),\n        (None, Some(partition_spec), Some(sort_order)) => table_creation_builder\n            .partition_spec(partition_spec)\n            .sort_order(sort_order)\n            .build(),\n        (None, Some(partition_spec), None) => table_creation_builder\n            .partition_spec(partition_spec)\n            .build(),\n        (None, None, Some(sort_order)) => table_creation_builder.sort_order(sort_order).build(),\n        (None, None, None) => table_creation_builder.build(),\n    };\n\n    catalog\n        .create_table(&namespace, table_creation)\n        .await\n        .map_err(|e| SinkError::Iceberg(anyhow!(e)))\n        .context(\"failed to create iceberg table\")?;\n    Ok(true)\n}\n\nasync fn create_namespace_if_not_exists(\n    catalog: &dyn Catalog,\n    namespace: &NamespaceIdent,\n) -> Result<()> {\n    let mut namespaces = vec![namespace.clone()];\n    let mut parent = namespace.parent();\n    while let Some(parent_namespace) = parent {\n        parent = parent_namespace.parent();\n        namespaces.push(parent_namespace);\n    }\n\n    for namespace in namespaces.into_iter().rev() {\n        if !catalog\n            .namespace_exists(&namespace)","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/create_table.rs#L250-L286","documentation":"This is the final step of table creation: catalog.create_table(&namespace, table_creation). Any failure returned by the catalog (namespace missing, permission denied, table already created concurrently, invalid location, storage errors) is wrapped into SinkError::Iceberg with the context 'failed to create iceberg table'.","triggerScenarios":"create_table_if_not_exists_impl reaches catalog.create_table and the catalog client returns Err — e.g. the namespace does not exist and creation failed, the location bucket is not writable, credentials lack permission, or a concurrent process created the table between the table_exists check and create.","commonSituations":"Object storage credentials/permissions misconfigured; namespace was deleted between create_namespace_if_not_exists and create_table; REST catalog rejecting the request (quota, schema conflicts); transient catalog/storage outages.","solutions":["Inspect the chained underlying error for the catalog's response (auth, permission, location).","Verify the table location's bucket/prefix exists and RisingWave's credentials can write to it.","Confirm the namespace exists (create_namespace_if_not_exists ran successfully) and wasn't removed concurrently.","Retry if the failure is transient; if the table was created concurrently, the existing table will be validated instead."],"exampleFix":"// before: IAM role lacks s3:PutObject on the location\nWITH (connector='iceberg', warehouse='s3://bucket/iceberg/', s3.access.key='...', ...)\n// after: grant write permissions on the bucket/prefix or fix the access key\naws s3api put-object --bucket bucket --key iceberg/test --body /dev/null # verify write access first","handlingStrategy":"retry","validationCode":"// Pre-flight: verify write access to the target location and namespace existence\ncatalog.namespace_exists(&namespace).await?;\n// and verify storage credentials, e.g.:\naws s3api put-object --bucket my-bucket --key iceberg/.write-test --body /dev/null","typeGuard":null,"tryCatchPattern":"match catalog.create_table(&namespace, table_creation).await {\n    Err(e) if is_retryable(&e) => retry_with_backoff(3, || create_table(...)),\n    Err(e) => Err(SinkError::Iceberg(anyhow!(e)).context(\"failed to create iceberg table\")),\n    Ok(t) => Ok(t),\n}","preventionTips":["Verify object-store credentials have write permission on the warehouse prefix before creating sinks.","Ensure create_namespace_if_not_exists succeeded and the namespace isn't deleted concurrently.","Handle the table-exists race by falling back to validation of the existing table.","Monitor catalog/storage availability and retry transient failures."],"tags":["rust","iceberg","catalog","create-table"],"backgroundTag":"database-write-failed","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"}