OrchardCMS/OrchardCore · error · InvalidOperationException

The 'OrchardCore.SignalR.Azure' and…

Error message

The 'OrchardCore.SignalR.Azure' and 'OrchardCore.SignalR.Redis' features cannot be enabled together.

What it means

Mirror implementation of the backplane guard in the SignalR.Redis module: when its Startup runs, it checks the service collection for the backplane registration marker and throws InvalidOperationException if the Azure backplane feature was already enabled, preventing two SignalR backplanes on one tenant.

Solutions

  1. Disable either the Redis or the Azure SignalR feature so exactly one backplane is active.
  2. Remove one of the features from recipe/setup JSON that provisions the tenant.
  3. Choose the desired backplane up front and document it to prevent toggling both on.

Example fix

// before (tenant features)
"OrchardCore.SignalR.Azure", "OrchardCore.SignalR.Redis"
// after
"OrchardCore.SignalR.Azure"
Defensive patterns

Strategy: validation

Validate before calling

var backplanes = new[] { "OrchardCore.SignalR.Redis", "OrchardCore.SignalR.Azure" }
    .Where(f => tenantFeatures.Contains(f)).ToList();
if (backplanes.Count > 1) throw new InvalidOperationException($"Only one backplane allowed, found: {string.Join(',', backplanes)}");

Type guard

const hasSingleBackplane = (fs) => ['OrchardCore.SignalR.Redis','OrchardCore.SignalR.Azure'].filter(f => fs.includes(f)).length === 1;

Try / catch

try {
  await enableFeatureAsync("OrchardCore.SignalR.Redis");
} catch (InvalidOperationException ex) when (ex.Message.Contains("cannot be enabled together")) {
  logger.LogWarning("Azure backplane already enabled; pick one.");
}

Prevention

When it happens

Trigger: Enabling both OrchardCore.SignalR.Redis and OrchardCore.SignalR.Azure features for the same tenant; a recipe enabling both; enabling Redis after Azure in the same request pipeline setup.

Common situations: Admin enables Azure SignalR while Redis is already configured via appsettings-driven feature list; duplicated recipes; test tenants that combined both backplane features.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/1554468c07196086. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.SignalR.Redis/Startup.cs:43

            return;
        }

        EnsureNoBackplaneIsRegistered(services);

        services
            .AddSignalR()
            .AddStackExchangeRedis();

        services.AddTransient<IConfigureOptions<SignalRRedisOptions>, SignalRRedisOptionsConfiguration>();
    }

    private static void EnsureNoBackplaneIsRegistered(IServiceCollection services)
    {
        if (services.Any(descriptor =>
            descriptor.IsKeyedService &&
            string.Equals(descriptor.ServiceKey as string, BackplaneRegistrationKey, StringComparison.Ordinal)))
        {
            throw new InvalidOperationException(
                $"The '{AzureBackplaneFeature}' and '{RedisBackplaneFeature}' features cannot be enabled together.");
        }

        services.AddKeyedSingleton<object>(BackplaneRegistrationKey, new object());
    }
}

internal sealed class SignalRRedisOptionsConfiguration : IConfigureOptions<SignalRRedisOptions>
{
    private readonly RedisOptions _redisOptions;
    private readonly string _tenantName;

    public SignalRRedisOptionsConfiguration(IOptions<RedisOptions> redisOptions, ShellSettings shellSettings)
    {
        _redisOptions = redisOptions.Value;
        _tenantName = shellSettings.Name;
    }

View on GitHub (pinned to 4306c0717f)