{"record":{"id":"9faaca0f23d67dd3","repo":"dotnet/orleans","slug":"load-must-complete-successfully-before-store-can-b","errorCode":null,"errorMessage":"Load must complete successfully before Store can be called again after a failed Store operation.","messagePattern":"Load must complete successfully before Store can be called again after a failed Store operation\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Transactions.AzureStorage/TransactionalState/AzureTableTransactionalStateStorage.cs","lineNumber":129,"sourceCode":"\n                    TransactionalStateMetaData metadata = JsonConvert.DeserializeObject<TransactionalStateMetaData>(this.key.Metadata!, this.jsonSettings)!;\n                    var result = new TransactionalStorageLoadResponse<TState>(this.key.ETag.ToString(), committedState, this.key.CommittedSequenceId, metadata, PrepareRecordsToRecover);\n                    _storeRequiresLoad = false;\n                    return result;\n                }\n            }\n            catch (Exception ex)\n            {\n                LogErrorTransactionalStateLoadFailed(ex);\n                throw;\n            }\n        }\n\n        public async Task<string> Store(string? expectedETag, TransactionalStateMetaData metadata, List<PendingTransactionState<TState>>? statesToPrepare, long? commitUpTo, long? abortAfter)\n        {\n            if (_storeRequiresLoad)\n            {\n                throw new InvalidOperationException(\"Load must complete successfully before Store can be called again after a failed Store operation.\");\n            }\n\n            var keyETag = key.ETag.ToString();\n            if ((!string.IsNullOrWhiteSpace(keyETag) || !string.IsNullOrWhiteSpace(expectedETag)) && keyETag != expectedETag)\n            {\n                throw new ArgumentException(nameof(expectedETag), \"Etag does not match\");\n            }\n\n            try\n            {\n                return await StoreCore(metadata, statesToPrepare, commitUpTo, abortAfter).ConfigureAwait(false);\n            }\n            catch\n            {\n                _storeRequiresLoad = true;\n                throw;\n            }\n        }","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Transactions.AzureStorage/TransactionalState/AzureTableTransactionalStateStorage.cs#L111-L147","documentation":"Thrown by AzureTableTransactionalStateStorage.Store when the _storeRequiresLoad flag is set, which flips true only after a prior Store threw. The storage is now in an uncertain state and insists on a fresh Load to re-sync the etag and state before any further write.","triggerScenarios":"A previous Store call failed (network error, conflict, etc.), setting _storeRequiresLoad; the caller retried Store without calling Load first.","commonSituations":"Retry loops that call Store again after InconsistentStateException; an exception in the transaction commit path that the surrounding code swallows before re-attempting.","solutions":["Call Load on the transactional state storage before retrying Store.","Do not retry Store on the same instance after a failure; let the runtime re-activate the grain.","Investigate and fix the root cause of the original Store failure (etag conflict, throttling)."],"exampleFix":"// before\ntry { await storage.Store(...); }\ncatch { await storage.Store(...); } // throws again: _storeRequiresLoad\n\n// after\ntry { await storage.Store(...); }\ncatch { await storage.Load(); /* re-sync then retry */ await storage.Store(...); }","handlingStrategy":"validation","validationCode":"if (_storeRequiresLoad) await storage.Load();\nawait storage.Store(etag, metadata, states, commit, abort);","typeGuard":null,"tryCatchPattern":"try { await storage.Store(...); }\ncatch (Exception) { await storage.Load(); throw; }","preventionTips":["Never retry Store on the same instance after a failure without Load.","Let the grain reactivate on persistent store errors."],"tags":["transactions","azure-table","state-recovery","azure"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}