dotnet/orleans · critical · InvalidOperationException

Journal format key '{journalFormatKey}' requires keyed servi

Error message

Journal format key '{journalFormatKey}' requires keyed service '{typeof(IJournalFormat).FullName}', but none was registered.

What it means

Thrown by ValidateJournalFormat when no keyed service IJournalFormat is registered under the configured journal-format key. The Azure Table journal provider delegates serialization to a pluggable IJournalFormat resolved by key from DI; a missing registration means there is no format to read or write journals.

Source

Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorageProvider.cs:130

    {
        try
        {
            journalId = new JournalId(value);
            return true;
        }
        catch (ArgumentException)
        {
            journalId = default;
            return false;
        }
    }

    private static void ValidateJournalFormat(IServiceProvider serviceProvider, string journalFormatKey)
    {
        var journalFormat = serviceProvider.GetKeyedService<IJournalFormat>(journalFormatKey);
        if (journalFormat is null)
        {
            throw new InvalidOperationException(
                $"Journal format key '{journalFormatKey}' requires keyed service '{typeof(IJournalFormat).FullName}', but none was registered.");
        }

        if (!string.Equals(journalFormat.FormatKey, journalFormatKey, StringComparison.Ordinal))
        {
            throw new InvalidOperationException(
                $"Journal format key '{journalFormatKey}' resolved format '{journalFormat.GetType().FullName}', but its {nameof(IJournalFormat.FormatKey)} is '{journalFormat.FormatKey}'. " +
                "Register the journal format using the same key it reports.");
        }
    }

    private static string ValidateJournalFormatKey(string? journalFormatKey)
    {
        if (string.IsNullOrWhiteSpace(journalFormatKey))
        {
            throw new InvalidOperationException("The configured journal format key must be non-empty.");
        }

View on GitHub (pinned to fca799fa70)

Solutions

  1. Register the IJournalFormat keyed service with the exact key, e.g. services.AddKeyedSingleton<IJournalFormat, JsonJournalFormat>('json').
  2. Match JournaledStateManagerOptions.JournalFormatKey to the key used at registration.
  3. Ensure the journal-format package (e.g. Orleans.Journaling.Json) is referenced and its Add* extension is called.

Example fix

// before
services.Configure<JournaledStateManagerOptions>(o => o.JournalFormatKey = 'json');
// (no IJournalFormat registration)
// after
services.AddJournalFormat<JsonJournalFormat>('json');
services.Configure<JournaledStateManagerOptions>(o => o.JournalFormatKey = 'json');
Defensive patterns

Strategy: validation

Validate before calling

var fmt = serviceProvider.GetKeyedService<IJournalFormat>(journalFormatKey);
if (fmt is null) throw new InvalidOperationException($"Register IJournalFormat for key '{journalFormatKey}'.");

Type guard

static bool IsJournalFormatRegistered(IServiceProvider sp, string key) => sp.GetKeyedService<IJournalFormat>(key) is not null;

Prevention

When it happens

Trigger: JournaledStateManagerOptions.JournalFormatKey is set (e.g. 'json') but the corresponding AddJournalFormat<JsonJournalFormat>('json', ...) call was never made, so serviceProvider.GetKeyedService<IJournalFormat>(key) returns null during provider construction.

Common situations: Upgrading or removing a journal-format package without re-registering it; a typo between the registered key and the configured JournalFormatKey; conditional registration that did not execute in the current environment.

Related errors


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