{"record":{"id":"fb8f81275cd9920e","repo":"dotnet/orleans","slug":"could-not-load-a-consistent-azure-table-transactio","errorCode":null,"errorMessage":"Could not load a consistent Azure Table transactional state snapshot.","messagePattern":"Could not load a consistent Azure Table transactional state snapshot\\.","errorType":"exception","errorClass":"InconsistentStateException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Transactions.AzureStorage/TransactionalState/AzureTableTransactionalStateStorage.cs","lineNumber":297,"sourceCode":"                    return (keyBefore, loadedStates);\n                }\n\n                if (versionBefore is null && versionAfter is null)\n                {\n                    // Legacy partitions do not have boundary rows. During rolling upgrades, older\n                    // writers also leave existing boundaries stale, so torn reads remain allowed\n                    // until every writer is upgraded to advance them.\n                    return (keyBefore, loadedStates);\n                }\n\n                if (versionBefore is not null\n                    && string.Equals(versionBefore, versionAfter, StringComparison.Ordinal))\n                {\n                    return (keyBefore, loadedStates);\n                }\n            }\n\n            throw new InconsistentStateException(\n                \"Could not load a consistent Azure Table transactional state snapshot.\",\n                storedEtag: versionBefore ?? \"null\",\n                currentEtag: versionAfter ?? \"null\");\n        }\n\n        private async Task<(\n            KeyEntity Key,\n            List<KeyValuePair<long, StateEntity>> States,\n            bool IsPaginated,\n            string? LowerBoundaryVersion,\n            string? UpperBoundaryVersion)> ReadSnapshot()\n        {\n            var query = AzureTableUtils.RangeQuery(this.partition, LowerBoundaryRowKey, UpperBoundaryRowKey);\n            var key = CreateFreshKey();\n            var states = new List<KeyValuePair<long, StateEntity>>();\n            var pageCount = 0;\n            string? lowerBoundaryVersion = null;\n            string? upperBoundaryVersion = null;","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Transactions.AzureStorage/TransactionalState/AzureTableTransactionalStateStorage.cs#L279-L315","documentation":"Thrown by AzureTableTransactionalStateStorage when a consistent read of the transactional snapshot cannot be obtained: the etag (version) read before and after paginated reads differs, indicating a concurrent write during the load. Wraps the conflict as an InconsistentStateException with stored vs current etags.","triggerScenarios":"A writer commits to the partition between the pre- and post-read version checks during LoadSnapshot; pagination across multiple table segments amplifies the race window.","commonSituations":"High write contention on a transactional grain; large state forcing multi-page reads; concurrent activations.","solutions":["Retry the transactional operation; the runtime typically re-drives the grain call.","Reduce write contention / co-locate related grains to lower cross-partition races.","Ensure pagination boundaries are advanced (newer Orleans versions tighten torn-read protection)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await storage.Load(); }\ncatch (InconsistentStateException) { await Task.Delay(backoff); await storage.Load(); }","preventionTips":["Allow the runtime to re-drive the grain call on InconsistentStateException.","Minimize write contention to shrink the torn-read window."],"tags":["transactions","azure-table","optimistic-concurrency","azure"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}