{"record":{"id":"9f17e13bf535c98e","repo":"dotnet/orleans","slug":"table-tabledescription-tablename-has-a-status-of","errorCode":null,"errorMessage":"Table {tableDescription.TableName} has a status of {tableDescription.TableStatus} and can't be updated automatically.","messagePattern":"Table (.+?) has a status of (.+?) and can't be updated automatically\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/AWS/Shared/Storage/DynamoDBStorage.cs","lineNumber":267,"sourceCode":"            }\n            catch (Exception exc)\n            {\n                LogErrorCouldNotCreateTable(_logger, exc, tableName);\n                throw;\n            }\n        }\n\n        private async ValueTask UpdateTableAsync(TableDescription tableDescription, List<AttributeDefinition> attributes, List<GlobalSecondaryIndex>? secondaryIndexes = null, string? ttlAttributeName = null, CancellationToken cancellationToken = default)\n        {\n            if (!this._updateIfExists)\n            {\n                LogWarningTableNotUpdated(_logger, tableDescription.TableName);\n                return;\n            }\n\n            if (!_updateTableValidTableStatuses.Contains(tableDescription.TableStatus))\n            {\n                throw new InvalidOperationException($\"Table {tableDescription.TableName} has a status of {tableDescription.TableStatus} and can't be updated automatically.\");\n            }\n\n            if (tableDescription.TableStatus == TableStatus.CREATING\n                || tableDescription.TableStatus == TableStatus.UPDATING)\n            {\n                tableDescription = await TableWaitOnStatusAsync(tableDescription.TableName, tableDescription.TableStatus, TableStatus.ACTIVE, cancellationToken: cancellationToken);\n            }\n\n            var request = new UpdateTableRequest\n            {\n                TableName = tableDescription.TableName,\n                AttributeDefinitions = attributes,\n                BillingMode = this._useProvisionedThroughput ? BillingMode.PROVISIONED : BillingMode.PAY_PER_REQUEST,\n                ProvisionedThroughput = _provisionedThroughput,\n                GlobalSecondaryIndexUpdates = this._useProvisionedThroughput\n                    ? tableDescription.GlobalSecondaryIndexes?.Select(gsi => new GlobalSecondaryIndexUpdate\n                    {\n                        Update = new UpdateGlobalSecondaryIndexAction","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/AWS/Shared/Storage/DynamoDBStorage.cs#L249-L285","documentation":"Thrown by DynamoDBStorage.UpdateTableAsync when the existing table's TableStatus is not one of CREATING, UPDATING, or ACTIVE (the set held by _updateTableValidTableStatuses) and updateIfExists is true. The library only auto-updates tables it considers healthy/transitioning; statuses like DELETING, ARCHIVED, or INACCESSIBLE_ENCRYPTION_CREDENTIALS are rejected so it does not fight an in-flight lifecycle operation.","triggerScenarios":"Produced during provider init when the table already exists, UpdateIfExists is true, and DescribeTable returns a status outside the valid set. Triggered by a table currently being deleted, an archived table being reused, or a table whose KMS encryption key became inaccessible.","commonSituations":"Reusing a table that someone started deleting out-of-band; pointing the provider at an archived table; a KMS key rotation that left the table INACCESSIBLE_ENCRYPTION_CREDENTIALS; manual table operations colliding with silo startup.","solutions":["Wait for the table to return to ACTIVE (or finish DELETING) and restart the silo, or recreate the table.","If the table is in a bad state (ARCHIVED / INACCESSIBLE_ENCRYPTION_CREDENTIALS), resolve the underlying AWS issue (restore KMS key access, restore the table).","If you intentionally manage the schema out-of-band, set UpdateIfExists = false so the provider does not attempt auto-update.","Confirm no concurrent operator/script is deleting or archiving the table during deployments."],"exampleFix":"// before: provider tries to update a table that is DELETING/ARCHIVED\nopt.UpdateIfExists = true;\n\n// after: either let the table settle to ACTIVE, or disable auto-update\nopt.UpdateIfExists = false; // you manage schema out-of-band\n// then ensure the table is ACTIVE before the silo starts","handlingStrategy":"validation","validationCode":"// Before startup, ensure the target table is in an updatable status (or absent so it can be created)\nvar statuses = new[] { TableStatus.CREATING, TableStatus.UPDATING, TableStatus.ACTIVE };\nvar desc = await DescribeExistingTableAsync(tableName);\nif (desc is not null && !statuses.Contains(desc.TableStatus) && opt.UpdateIfExists)\n    throw new InvalidOperationException($\"Table {tableName} is {desc.TableStatus}; resolve before starting the silo\");","typeGuard":"static bool IsUpdatableStatus(TableStatus s) =>\n    s == TableStatus.CREATING || s == TableStatus.UPDATING || s == TableStatus.ACTIVE;","tryCatchPattern":"try { await silo.StartAsync(); }\ncatch (InvalidOperationException ix) when (ix.Message.Contains(\"can't be updated automatically\"))\n{\n    _logger.LogCritical(\"DynamoDB table is in a non-updatable status; resolve (restore/delete) or set UpdateIfExists=false\");\n    throw;\n}","preventionTips":["Do not delete/archive a table out-of-band while the silo is starting.","If you manage schema manually, set UpdateIfExists = false.","Resolve KMS/encryption issues before reusing an ARCHIVED or INACCESSIBLE table.","Coordinate deployments so only one operator touches the table lifecycle."],"tags":["dynamodb","table-status","schema-update","config"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}