dotnet/orleans · error · InconsistentStateException
Could not load a consistent Azure Table transactional state
Error message
Could not load a consistent Azure Table transactional state snapshot.
What it means
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.
Source
Thrown at src/Azure/Orleans.Transactions.AzureStorage/TransactionalState/AzureTableTransactionalStateStorage.cs:297
return (keyBefore, loadedStates);
}
if (versionBefore is null && versionAfter is null)
{
// Legacy partitions do not have boundary rows. During rolling upgrades, older
// writers also leave existing boundaries stale, so torn reads remain allowed
// until every writer is upgraded to advance them.
return (keyBefore, loadedStates);
}
if (versionBefore is not null
&& string.Equals(versionBefore, versionAfter, StringComparison.Ordinal))
{
return (keyBefore, loadedStates);
}
}
throw new InconsistentStateException(
"Could not load a consistent Azure Table transactional state snapshot.",
storedEtag: versionBefore ?? "null",
currentEtag: versionAfter ?? "null");
}
private async Task<(
KeyEntity Key,
List<KeyValuePair<long, StateEntity>> States,
bool IsPaginated,
string? LowerBoundaryVersion,
string? UpperBoundaryVersion)> ReadSnapshot()
{
var query = AzureTableUtils.RangeQuery(this.partition, LowerBoundaryRowKey, UpperBoundaryRowKey);
var key = CreateFreshKey();
var states = new List<KeyValuePair<long, StateEntity>>();
var pageCount = 0;
string? lowerBoundaryVersion = null;
string? upperBoundaryVersion = null;View on GitHub (pinned to fca799fa70)
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).
Defensive patterns
Strategy: retry
Try / catch
try { await storage.Load(); }
catch (InconsistentStateException) { await Task.Delay(backoff); await storage.Load(); } Prevention
- Allow the runtime to re-drive the grain call on InconsistentStateException.
- Minimize write contention to shrink the torn-read window.
When it happens
Trigger: 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.
Common situations: High write contention on a transactional grain; large state forcing multi-page reads; concurrent activations.
Related errors
- Etag does not match
- Azure Table transactional state storage conflict. Partition=
- Storage state corrupted: no record for committed state v{thi
- Load must complete successfully before Store can be called a
- Data too large to write to table. Size={0} MaxSize={1}
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/fb8f81275cd9920e.
Report an issue: GitHub.