{"record":{"id":"3dfed1b5fde5f1f1","repo":"databendlabs/databend","slug":"failed-to-refresh-iceberg-table-credentials-erro","errorCode":null,"errorMessage":"failed to refresh Iceberg table credentials: {error:?}","messagePattern":"failed to refresh Iceberg table credentials: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/storages/iceberg/src/credential.rs","lineNumber":108,"sourceCode":"\n#[async_trait]\ntrait VendedCredentialProvider: Send + Sync {\n    async fn load(&self) -> anyhow::Result<VendedCredential>;\n}\n\nstruct CatalogCredentialProvider {\n    catalog: Arc<dyn iceberg::Catalog>,\n    table_ident: TableIdent,\n}\n\n#[async_trait]\nimpl VendedCredentialProvider for CatalogCredentialProvider {\n    async fn load(&self) -> anyhow::Result<VendedCredential> {\n        let table = self\n            .catalog\n            .load_table(&self.table_ident)\n            .await\n            .map_err(|error| anyhow!(\"failed to refresh Iceberg table credentials: {error:?}\"))?;\n        VendedCredential::from_table(&table).ok_or_else(|| {\n            anyhow!(\"Iceberg load_table response did not contain vended credentials\")\n        })\n    }\n}\n\nstruct RefreshingAwsCredentialLoader {\n    provider: Arc<dyn VendedCredentialProvider>,\n    current: Mutex<VendedCredential>,\n}\n\nimpl RefreshingAwsCredentialLoader {\n    fn new(provider: Arc<dyn VendedCredentialProvider>, current: VendedCredential) -> Self {\n        Self {\n            provider,\n            current: Mutex::new(current),\n        }\n    }","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/storages/iceberg/src/credential.rs#L90-L126","documentation":"`CatalogCredentialProvider::load` refreshes vended credentials by calling the Iceberg catalog's `load_table`. If that catalog RPC fails for any reason, the failure is wrapped in this anyhow error. The credential provider needs a fresh load_table response to extract vended (temporary) credentials for the storage backend.","triggerScenarios":"Periodic or on-demand credential refresh when the Iceberg REST catalog rejects or fails the `load_table` call for `self.table_ident` — auth failures, catalog downtime, 404 on the table identifier, network errors.","commonSituations":"Expired catalog credentials, REST catalog base URL changed, table dropped/renamed externally in the catalog while Databend still references it, catalog service outage, TLS/DNS problems.","solutions":["Check the debug-formatted inner `error` to see the catalog HTTP status/cause.","Verify catalog credentials (catalog auth config) are valid and not expired.","Confirm the table identifier still exists in the catalog (`SHOW TABLES`, or curl the REST catalog).","Check catalog service availability and network reachability from the query node.","Retry — the refresh is retried downstream via `RefreshingAwsCredentialLoader`; a transient catalog blip may resolve itself."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"loop {\n    match provider.load().await {\n        Ok(c) => break c,\n        Err(e) if is_transient(&e) && retries < MAX => { retries += 1; sleep(backoff).await; }\n        Err(e) => return Err(e),\n    }\n}","preventionTips":["Monitor catalog health and credentials expiry","Keep table identifiers in sync with the catalog (handle external drops/renames)","Alert on repeated refresh failures rather than silently retrying forever"],"tags":["iceberg","catalog","credentials"],"backgroundTag":"api-request-failed","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}