dotnet/orleans · error · InvalidOperationException

AzureBlobJournalStorageProvider has not been initialized. En

Error message

AzureBlobJournalStorageProvider has not been initialized. Ensure the silo lifecycle has started before using journal storage.

What it means

Thrown by AzureBlobJournalStorageProvider.GetDefaultContainerClient when the default container client is null, meaning the provider has not run its lifecycle initialization. The provider subscribes to the silo lifecycle at RuntimeInitialize stage and creates the container there; calling ListAsync or other methods before that stage completes yields this error.

Source

Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureBlobJournalStorageProvider.cs:104

        }

        foreach (var journalId in journalIds.OrderBy(static journalId => journalId.Value, StringComparer.Ordinal))
        {
            cancellationToken.ThrowIfCancellationRequested();
            yield return journalId;
        }
    }

    public void Participate(ISiloLifecycle observer)
    {
        observer.Subscribe(
            nameof(AzureBlobJournalStorageProvider),
            ServiceLifecycleStage.RuntimeInitialize,
            onStart: Initialize);
    }

    private BlobContainerClient GetDefaultContainerClient()
        => _defaultContainer ?? throw new InvalidOperationException(
            $"{nameof(AzureBlobJournalStorageProvider)} has not been initialized. Ensure the silo lifecycle has started before using journal storage.");

    private static bool TryParseJournalId(string value, out JournalId journalId)
    {
        try
        {
            journalId = new JournalId(value);
            return true;
        }
        catch (ArgumentException)
        {
            journalId = default;
            return false;
        }
    }

    private static IJournalFormat GetJournalFormat(IServiceProvider serviceProvider, string journalFormatKey)
    {

View on GitHub (pinned to fca799fa70)

Solutions

  1. Ensure the silo is fully started before calling ListAsync; in tests, use a test hosting harness that drives the lifecycle.
  2. Delay listing journals until after the RuntimeInitialize lifecycle stage.
  3. If you need listing outside the silo, construct a standalone BlobContainerClient and query the container directly.

Example fix

// before (in a test)
var provider = new AzureBlobJournalStorageProvider(...);
await foreach (var id in provider.ListAsync()) { ... } // throws: not initialized

// after
await provider.Participate(...); // or use a TestHost that runs lifecycle stages
await foreach (var id in provider.ListAsync()) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// In a test harness, drive the lifecycle before calling ListAsync:
var lifecycle = new TestSiloLifecycle();
provider.Participate(lifecycle);
await lifecycle.OnStart(RuntimeInitializeStage);
await foreach (var id in provider.ListAsync()) { ... }

Try / catch

try { await foreach (var id in provider.ListAsync(ct)) { ... } }
catch (InvalidOperationException ex) when (ex.Message.Contains("has not been initialized"))
{
    logger.LogWarning("Journal storage queried before silo RuntimeInitialize; deferring.");
}

Prevention

When it happens

Trigger: Invoking provider.ListAsync(...) (or any path through GetDefaultContainerClient) before the silo lifecycle has reached RuntimeInitialize and run the Initialize callback. Commonly happens in tests, startup hooks, or grain constructors that run before the silo is fully started.

Common situations: Unit/integration tests that construct the provider directly without driving the lifecycle; calling ListAsync from a grain's OnActivateAsync before the hosting stage completes; ordering misconfiguration where journal storage is used before RuntimeInitialize.

Related errors


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