dotnet/efcore · critical · InvalidOperationException

A call was made to '{optionCall}' that changed an option tha

Error message

A call was made to '{optionCall}' that changed an option that must be constant within a service provider, but Entity Framework is not building its own internal service provider. Either allow Entity Framework to build the service provider by removing the call to '{useInternalServiceProvider}', or ensure that the configuration for '{optionCall}' does not change for all uses of a given service provider passed to '{useInternalServiceProvider}'.

What it means

Thrown by CosmosSingletonOptions.Validate when a DbContext sharing an internal service provider (set via UseInternalServiceProvider) supplies Cosmos configuration that differs from what was previously cached on the singleton. Validate compares AccountEndpoint, AccountKey, TokenCredential, ConnectionString, Region, PreferredRegions, LimitToEndpoint, ConnectionMode, WebProxy, several timeouts, TCP limits, EnableContentResponseOnWrite, HttpClientFactory, and EnableBulkExecution. Any mismatch on any of those across contexts sharing the provider throws.

Source

Thrown at src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs:225

                || TokenCredential != cosmosOptions.TokenCredential
                || ConnectionString != cosmosOptions.ConnectionString
                || Region != cosmosOptions.Region
                || !StructuralComparisons.StructuralEqualityComparer.Equals(PreferredRegions, cosmosOptions.PreferredRegions)
                || LimitToEndpoint != cosmosOptions.LimitToEndpoint
                || ConnectionMode != cosmosOptions.ConnectionMode
                || WebProxy != cosmosOptions.WebProxy
                || RequestTimeout != cosmosOptions.RequestTimeout
                || OpenTcpConnectionTimeout != cosmosOptions.OpenTcpConnectionTimeout
                || IdleTcpConnectionTimeout != cosmosOptions.IdleTcpConnectionTimeout
                || GatewayModeMaxConnectionLimit != cosmosOptions.GatewayModeMaxConnectionLimit
                || MaxTcpConnectionsPerEndpoint != cosmosOptions.MaxTcpConnectionsPerEndpoint
                || MaxRequestsPerTcpConnection != cosmosOptions.MaxRequestsPerTcpConnection
                || EnableContentResponseOnWrite != cosmosOptions.EnableContentResponseOnWrite
                || HttpClientFactory != cosmosOptions.HttpClientFactory
                || EnableBulkExecution != cosmosOptions.EnableBulkExecution
            ))
        {
            throw new InvalidOperationException(
                CoreStrings.SingletonOptionChanged(
                    nameof(CosmosDbContextOptionsExtensions.UseCosmos),
                    nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
        }
    }
}

View on GitHub (pinned to dbf9771522)

Solutions

  1. Make the Cosmos connection options identical for every context that shares the internal service provider (same endpoint, region, mode, bulk, etc.).
  2. If per-tenant options are required, use a separate internal service provider (a separate pool) per distinct Cosmos configuration, or stop calling UseInternalServiceProvider and let EF build its own provider per context.
  3. Centralize UseCosmos configuration in one place and inject the same DbContextOptions instance to all contexts.

Example fix

// before
services.AddDbContextPool<TenantAdb>(o => o
    .UseInternalServiceProvider(sp)
    .UseCosmos(endpointA, key, "db"));
services.AddDbContextPool<TenantBdb>(o => o
    .UseInternalServiceProvider(sp)        // same provider, different endpoint -> throws
    .UseCosmos(endpointB, key, "db"));

// after: give each distinct Cosmos config its own provider
services.AddDbContextPool<TenantAdb>(o => o
    .UseInternalServiceProvider(spA)
    .UseCosmos(endpointA, key, "db"));
services.AddDbContextPool<TenantBdb>(o => o
    .UseInternalServiceProvider(spB)
    .UseCosmos(endpointB, key, "db"));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure all DbContexts sharing an internal service provider use identical Cosmos options
var snapshot = new { Endpoint, Key, Region, ConnectionMode, BulkEnabled } /* extract from your config */;
// in DI setup, throw if a second context registers different values against the same provider pool

Try / catch

// At startup, exercise one operation from each pooled context inside a try/catch
try { await using var ctx = provider.GetRequiredService<MyDb>(); await ctx.Database.EnsureCreatedAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("must be constant within a service provider"))
{ /* log and abort startup: Cosmos options differ across pooled contexts */ }

Prevention

When it happens

Trigger: Calling DbContextOptionsBuilder.UseInternalServiceProvider(pool) and then registering two contexts whose UseCosmos calls differ (different endpoint, region, connection mode, bulk setting, etc.).

Common situations: Using AddDbContextPool or an explicit pooled internal provider with multi-tenant Cosmos where each tenant has a different endpoint/key. Dynamically switching ConnectionMode or Region per request on a pooled context.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/2903f262a8f5d215. Report an issue: GitHub.