dotnet/orleans · error · InvalidOperationException

This instance has not been initialized. Ensure that Initiali

Error message

This instance has not been initialized. Ensure that InitializeGatewayListProvider is called to initialize this instance before use.

What it means

InvalidOperationException from the Session property getter on CassandraGatewayListProvider: the backing _session is null because IGatewayListProvider.InitializeGatewayListProvider has not completed. The message (via NotInitializedMessage) tells you to call InitializeGatewayListProvider. Identical pattern to the clustering table's Session guard.

Source

Thrown at src/Cassandra/Orleans.Clustering.Cassandra/CassandraGatewayListProvider.cs:46

    bool IGatewayListProvider.IsUpdatable => true;

    public CassandraGatewayListProvider(
        IOptions<ClusterOptions> clusterOptions,
        IOptions<GatewayOptions> gatewayOptions,
        IOptions<CassandraClusteringOptions> options,
        IOptions<ClusterMembershipOptions> clusterMembershipOptions,
        IServiceProvider serviceProvider)
    {
        _identifier = $"{clusterOptions.Value.ServiceId}-{clusterOptions.Value.ClusterId}";
        _options = options.Value;
        _serviceProvider = serviceProvider;

        _maxStaleness = gatewayOptions.Value.GatewayListRefreshPeriod;
        _ttlSeconds = _options.GetCassandraTtlSeconds(clusterMembershipOptions.Value);
    }

    private ISession Session => _session ?? throw new InvalidOperationException(NotInitializedMessage);

    private OrleansQueries Queries => _queries ?? throw new InvalidOperationException(NotInitializedMessage);

    async Task IGatewayListProvider.InitializeGatewayListProvider()
    {
        _session = await _options.CreateSessionAsync(_serviceProvider);
        if (_session is null)
        {
            throw new InvalidOperationException($"Session created from configuration '{nameof(CassandraClusteringOptions)}' is null.");
        }

        _queries = await OrleansQueries.CreateInstance(_session);

        await _queries.EnsureTableExistsAsync(_options.InitializeRetryMaxDelay, _ttlSeconds);
    }
    
    async Task<IList<Uri>> IGatewayListProvider.GetGateways()
    {

View on GitHub (pinned to fca799fa70)

Solutions

  1. Register the provider via the Orleans client hosting extension (UseCassandraGatewayListProvider / AddCassandraClustering) so the runtime calls InitializeGatewayListProvider.
  2. In tests, await InitializeGatewayListProvider before calling GetGateways.
  3. If initialization is failing earlier, inspect logs for CreateSessionAsync/EnsureTableExistsAsync errors and fix those first.

Example fix

// before
var gw = host.Services.GetRequiredService<IGatewayListProvider>();
await gw.GetGateways(); // throws: Session null

// after
var gw = host.Services.GetRequiredService<IGatewayListProvider>();
await gw.InitializeGatewayListProvider();
await gw.GetGateways();
Defensive patterns

Strategy: validation

Validate before calling

await gw.InitializeGatewayListProvider();
await gw.GetGateways();

Try / catch

try { await gw.GetGateways(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("InitializeGatewayListProvider"))
{ logger.LogError(ex, "Gateway provider used before init"); throw; }

Prevention

When it happens

Trigger: Calling GetGateways() (or any code path that reads Session) before InitializeGatewayListProvider finishes assigning _session. The provider caches results but the first access to Session still requires initialization.

Common situations: Using the Cassandra gateway provider without registering it through the client hosting extension, or a client that resolves the provider and calls GetGateways in a test before initialization. Also when CreateSessionAsync returned null earlier (see error 353), leaving _session unset.

Related errors


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