dotnet/orleans · error · InvalidOperationException
AzureTableJournalStorageProvider has not been initialized. E
Error message
AzureTableJournalStorageProvider has not been initialized. Ensure the silo lifecycle has started before using journal storage.
What it means
The default InitializedTableClientProvider.GetTableClient (AzureTableJournalStorage.cs:1318) was called before SetTableClient had supplied a TableClient. The TableClient is assigned during silo lifecycle initialization; using journal storage before that phase completes throws this InvalidOperationException. It signals a lifecycle ordering bug, not a data problem.
Source
Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorage.cs:1319
public string? JournalFormatKey { get; }
public TableClientProvider TableClientProvider { get; }
public AzureTableJournalStorageInstruments Instruments { get; }
}
internal abstract class TableClientProvider
{
public abstract TableClient GetTableClient();
}
internal sealed class InitializedTableClientProvider : TableClientProvider
{
private TableClient? _tableClient;
public override TableClient GetTableClient()
=> _tableClient ?? throw new InvalidOperationException(
$"{nameof(AzureTableJournalStorageProvider)} has not been initialized. Ensure the silo lifecycle has started before using journal storage.");
public void SetTableClient(TableClient tableClient)
{
ArgumentNullException.ThrowIfNull(tableClient);
_tableClient = tableClient;
}
}
}
View on GitHub (pinned to fca799fa70)
Solutions
- Defer journal access until after the silo/client has fully started (the storage's lifecycle OnActive has completed).
- In tests, call SetTableClient with a real or mock TableClient before exercising the storage.
- Ensure the consuming component participates in a lifecycle stage later than the storage provider.
Example fix
// before — journal used during early startup
public MyStartupService(JournalStorage s) { s.Read(...); }
// after — wait until lifecycle active
public Task OnActive(CancellationToken ct) { /* journal safe here */ } Defensive patterns
Strategy: validation
Validate before calling
// Ensure the provider is initialized before first use
try { _ = storageShared.TableClientProvider.GetTableClient(); }
catch (InvalidOperationException) { /* not yet initialized — defer use */ } Prevention
- Touch journal storage only after the silo/client has fully started.
- In tests, call SetTableClient before exercising the storage.
- Order consumers in a later lifecycle stage than the storage provider.
When it happens
Trigger: Any journal read/write issued before the AzureTableJournalStorageProvider's lifecycle OnActive has run and called SetTableClient; e.g., a grain or startup service that touches a journal during an earlier lifecycle stage.
Common situations: A hosted service or grain attempts journal access during Configure or earlier lifecycle phases; a test instantiates the storage and calls methods without driving the lifecycle; misordered DI such that a consumer resolves and uses the storage before the provider is initialized.
Related errors
- The configured Azure Table journal client provider returned
- Unknown Playground:Storage:Provider value '{storageProvider}
- WEBSITE_PRIVATE_PORTS must contain at least one TCP port.
- The required setting '{name}' isn't configured.
- AzureTable:ServiceUri must be an absolute HTTPS Azure Table
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/92e3524e9db19cd8.
Report an issue: GitHub.