apache/iceberg · error · IllegalStateException
Dynamo catalog table
Error message
Dynamo catalog table %s is not active, current status: %s
What it means
DynamoDbCatalog.checkTableActive() calls DescribeTable on the underlying DynamoDB catalog table and requires its status to be ACTIVE before performing catalog reads/writes. If the status differs (e.g. CREATING, UPDATING, DELETING), an IllegalStateException with this message is thrown because the catalog table cannot reliably serve requests.
Solutions
- Wait until `aws dynamodb describe-table --table-name <catalog-table>` reports ACTIVE before initializing the catalog; add retry/backoff around catalog initialization.
- Ensure the setup script does not delete/recreate the DynamoDB catalog table while clients are running.
- Catch IllegalStateException from catalog construction and retry after a delay if the status is transitioning (CREATING/UPDATING).
Example fix
// before DynamoDbCatalog catalog = new DynamoDbCatalog(); catalog.initialize(config); // may hit non-ACTIVE table // after waitUntilTableActive(catalogTableName); // poll DescribeTable until status == ACTIVE DynamoDbCatalog catalog = new DynamoDbCatalog(); catalog.initialize(config);
Defensive patterns
Strategy: retry
Validate before calling
DescribeTableResponse r = dynamo.describeTable(DescribeTableRequest.builder().tableName(catalogTable).build());
if (!r.table().tableStatus().equals(TableStatus.ACTIVE)) {
throw new IllegalStateException("Catalog table " + catalogTable + " is " + r.table().tableStatus());
} Try / catch
await.atMost(5, MINUTES).pollInterval(10, SECONDS).until(() -> {
try { catalog.initialize(config); return true; }
catch (IllegalStateException e) { return false; } // table still transitioning
}); Prevention
- Never delete/recreate the DynamoDB catalog table while clients are running
- Wait for ACTIVE status after any table-level change before starting the catalog
- Add readiness probes that poll DescribeTable before app startup
When it happens
Trigger: Any catalog operation that routes through checkTableActive while the DynamoDB catalog table is mid-update — table creation, deletion, or a TTL/throughput change leaving it in CREATING/UPDATING/DELETING state.
Common situations: Deployment scripts that delete and immediately recreate the catalog table, then start the catalog before the new table is ACTIVE; on-demand capacity mode switches; running tests against a table still being provisioned.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot create namespace
- Cannot delete non-empty namespace
- Cannot find default warehouse location: namespace
- Cannot find Dynamo catalog table
- Cannot find namespace
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0b6a2b6d03c29726.
Report an issue: GitHub.
Appendix: source
Thrown at aws/src/main/java/org/apache/iceberg/aws/dynamodb/DynamoDbCatalog.java:661
.build())
.billingMode(BillingMode.PAY_PER_REQUEST)
.build());
// wait for the dynamo table to complete provisioning, which takes around 10 seconds
Tasks.foreach(awsProperties.dynamoDbTableName())
.retry(CATALOG_TABLE_CREATION_WAIT_ATTEMPTS_MAX)
.throwFailureWhenFinished()
.onlyRetryOn(IllegalStateException.class)
.run(this::checkTableActive);
}
private void checkTableActive(String tableName) {
try {
DescribeTableResponse response =
dynamo.describeTable(DescribeTableRequest.builder().tableName(tableName).build());
TableStatus currentStatus = response.table().tableStatus();
if (!currentStatus.equals(TableStatus.ACTIVE)) {
throw new IllegalStateException(
String.format(
"Dynamo catalog table %s is not active, current status: %s",
tableName, currentStatus));
}
} catch (ResourceNotFoundException e) {
throw new IllegalStateException(
String.format("Cannot find Dynamo catalog table %s", tableName));
}
}
private boolean updateProperties(
Namespace namespace,
String updateExpression,
Map<String, AttributeValue> attributeValues,
Map<String, String> attributeNames) {
validateNamespace(namespace);
Map<String, AttributeValue> key = namespacePrimaryKey(namespace);
try {View on GitHub (pinned to 86d9c8fc54)