dotnet/orleans · critical · InvalidOperationException

Storage state corrupted: no record for committed state v{thi

Error message

Storage state corrupted: no record for committed state v{this.key.CommittedSequenceId}

What it means

Thrown by AzureTableTransactionalStateStorage during Load when the stored metadata references a committed sequence id (key.CommittedSequenceId) but no state entity for that version exists in the partition. This indicates the transactional state table is internally inconsistent / corrupted.

Source

Thrown at src/Azure/Orleans.Transactions.AzureStorage/TransactionalState/AzureTableTransactionalStateStorage.cs:73

                    // first time load
                    _storeRequiresLoad = false;
                    return new TransactionalStorageLoadResponse<TState>();
                }
                else
                {
                    TState committedState;
                    if (this.key.CommittedSequenceId == 0)
                    {
                        committedState = new TState();
                    }
                    else
                    {
                        if (!FindState(this.key.CommittedSequenceId, out var pos))
                        {
                            var error = $"Storage state corrupted: no record for committed state v{this.key.CommittedSequenceId}";
                            LogCriticalPartitionError(partition, error);
                            throw new InvalidOperationException(error);
                        }
                        committedState = states[pos].Value.GetState<TState>(this.jsonSettings);
                    }

                    var PrepareRecordsToRecover = new List<PendingTransactionState<TState>>();
                    for (int i = 0; i < states.Count; i++)
                    {
                        var kvp = states[i];

                        // pending states for already committed transactions can be ignored
                        if (kvp.Key <= key.CommittedSequenceId)
                            continue;

                        // upon recovery, local non-committed transactions are considered aborted
                        if (kvp.Value.TransactionManager == null)
                            break;

                        ParticipantId tm = JsonConvert.DeserializeObject<ParticipantId>(kvp.Value.TransactionManager, this.jsonSettings);

View on GitHub (pinned to fca799fa70)

Solutions

  1. Restore the missing state entity from a backup of the Azure Table.
  2. If recovery is impossible, reset the affected grain's transactional state (delete the partition so it re-initializes) and accept data loss for that actor.
  3. Engage Orleans transactional state recovery tooling or open an issue with the partition key and sequence id for diagnosis.
  4. Audit for external processes writing to the same table.
Defensive patterns

Strategy: try-catch

Try / catch

try { await storage.Load(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Storage state corrupted"))
{ /* quarantine partition, alert, do not retry blindly */ throw; }

Prevention

When it happens

Trigger: External modification or deletion of rows in the Azure Table that back transactional state; partial writes from a crashed silo that left metadata ahead of the actual state rows; manual table tampering.

Common situations: Operator deleting state entities manually; a storage account migration that dropped rows; an Orleans upgrade bug that changed the row-key scheme; catastrophic partial failure in an earlier batch.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/6cd0208eb225532d. Report an issue: GitHub.