dotnet/orleans · error · InvalidOperationException
The configured Azure Table journal client provider returned
Error message
The configured Azure Table journal client provider returned null.
What it means
The configured ITableClientProvider for Azure Table journal storage returned null from GetTableClient. The shared layer (AzureTableJournalStorage.cs:985) treats a null client as a fatal configuration defect because there is no valid table endpoint to use. This comes from a custom TableClientProvider implementation, not the default InitializedTableClientProvider (which throws its own error 218 instead).
Source
Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorage.cs:988
}
private ETag SetHeaderFromResponse(Response response, HeaderProviderState providerState)
{
// Force a reload before the next mutation if the service did not return the new header ETag.
if (response.Headers.ETag is { } eTag)
{
SetHeader(eTag, providerState);
return eTag;
}
SetHeader(eTag: default, providerState: default);
return default;
}
private TableClient GetTableClient()
{
var client = _shared.TableClientProvider.GetTableClient();
return client ?? throw new InvalidOperationException("The configured Azure Table journal client provider returned null.");
}
private static string FormatRowKey(string generation, long sequence)
=> string.Create(CultureInfo.InvariantCulture, $"{generation}-{sequence:D12}");
private static string[] CreateChunkPropertyNames()
{
var names = new string[MaxChunksPerEntity];
for (var i = 0; i < names.Length; i++)
{
names[i] = string.Create(CultureInfo.InvariantCulture, $"Data{i:D2}");
}
return names;
}
private HeaderState CreateHeaderState(TableEntity entity)
{View on GitHub (pinned to fca799fa70)
Solutions
- Make the custom TableClientProvider.GetTableClient() never return null — throw a meaningful exception if the client cannot be constructed.
- Verify the configuration values the provider reads (connection string, URI, credentials) are bound and non-null at startup.
- Register the provider and its dependencies correctly in the DI container so construction succeeds.
Example fix
// before
public override TableClient GetTableClient() => _client; // _client may be null
// after
public override TableClient GetTableClient()
=> _client ?? throw new InvalidOperationException("TableClient was not configured."); Defensive patterns
Strategy: validation
Validate before calling
var client = provider.GetTableClient();
if (client is null) throw new InvalidOperationException("TableClientProvider returned null at startup"); Type guard
static bool IsTableClientProviderValid(TableClientProvider p)
{
try { return p.GetTableClient() is not null; }
catch { return false; }
} Prevention
- Make custom TableClientProvider.GetTableClient() throw, never return null.
- Exercise the provider in a startup health check.
- Bind connection configuration before constructing the provider.
When it happens
Trigger: A user-supplied TableClientProvider subclass's GetTableClient() returns null; GetTableClient() in AzureTableJournalStorage.cs:987 receives null and throws.
Common situations: A custom provider lazily creates a client but its factory returned null (e.g., missing config section, null connection string parsed as null); a DI registration that builds the provider with unresolved dependencies; a provider written to return null-on-error instead of throwing.
Related errors
- Azure Table journal header belongs to journal id "{journalId
- AzureTableJournalStorageProvider has not been initialized. E
- Value cannot be null. (Parameter 'createClientCallback')
- Value cannot be null. (Parameter 'connectionString')
- Value cannot be null. (Parameter 'serviceUri')
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/c9f19130f01894aa.
Report an issue: GitHub.