{"record":{"id":"20b31e58d5e345e0","repo":"dotnet/orleans","slug":"session-created-from-configuration-cassandraclust","errorCode":null,"errorMessage":"Session created from configuration 'CassandraClusteringOptions' is null.","messagePattern":"Session created from configuration 'CassandraClusteringOptions' is null\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Cassandra/Orleans.Clustering.Cassandra/CassandraClusteringTable.cs","lineNumber":47,"sourceCode":"        IServiceProvider serviceProvider)\n    {\n        _clusterOptions = clusterOptions.Value;\n        _options = options.Value;\n        _identifier = $\"{_clusterOptions.ServiceId}-{_clusterOptions.ClusterId}\";\n        _serviceProvider = serviceProvider;\n        _ttlSeconds = _options.GetCassandraTtlSeconds(clusterMembershipOptions.Value);\n    }\n\n    private ISession Session => _session ?? throw new InvalidOperationException(NotInitializedMessage);\n\n    private OrleansQueries Queries => _queries ?? throw new InvalidOperationException(NotInitializedMessage);\n\n    async Task IMembershipTable.InitializeMembershipTable(bool tryInitTableVersion)\n    {\n        _session = await _options.CreateSessionAsync(_serviceProvider);\n        if (_session is null)\n        {\n            throw new InvalidOperationException($\"Session created from configuration '{nameof(CassandraClusteringOptions)}' is null.\");\n        }\n\n        _queries = await OrleansQueries.CreateInstance(_session);\n\n        await _queries.EnsureTableExistsAsync(_options.InitializeRetryMaxDelay, _ttlSeconds);\n\n        if (tryInitTableVersion)\n            await _queries.EnsureClusterVersionExistsAsync(_options.InitializeRetryMaxDelay, _identifier);\n    }\n\n    async Task IMembershipTable.DeleteMembershipTableEntries(string clusterId)\n    {\n        if (string.Compare(clusterId, _clusterOptions.ClusterId, StringComparison.InvariantCultureIgnoreCase) != 0)\n        {\n            throw new ArgumentException(\n                $\"Cluster id {clusterId} does not match CassandraClusteringTable value of '{_clusterOptions.ClusterId}'.\",\n                nameof(clusterId));\n        }","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Cassandra/Orleans.Clustering.Cassandra/CassandraClusteringTable.cs#L29-L65","documentation":"InvalidOperationException thrown inside InitializeMembershipTable when the user-supplied delegate CassandraClusteringOptions.CreateSessionAsync returns a null ISession. Orleans requires a valid Cassandra session; a null return indicates a misconfigured factory. The message names the options type so the misconfiguration is identifiable.","triggerScenarios":"CassandraClusteringOptions.CreateSessionAsync returns null. This delegate is responsible for building the ISession (cluster/builder); if it returns null, the table cannot proceed and initialization aborts before OrleansQueries is built.","commonSituations":"A custom CreateSessionAsync implementation with a missing return path (e.g. returns null on a not-found config), the default factory failing silently, or a DI scope where the session-creation service is not registered. Also seen when copy-pasting a sample that left the factory incomplete.","solutions":["Provide a CreateSessionAsync that always returns a non-null ISession (Cluster.Builder().AddContactPoint(...).Build().Connect(keyspace)).","Verify the session-creation dependencies (contact points, credentials, keyspace) are configured in CassandraClusteringOptions.","Throw a descriptive exception from inside CreateSessionAsync when session creation genuinely fails, instead of returning null."],"exampleFix":"// before\noptions.CreateSessionAsync = _ => Task.FromResult<ISession>(null!); // null -> this throw\n\n// after\noptions.CreateSessionAsync = async sp =>\n{\n    var cfg = sp.GetRequiredService<IOptions<CassandraConfig>>().Value;\n    var cluster = Cluster.Builder()\n        .AddContactPoints(cfg.ContactPoints)\n        .WithCredentials(cfg.User, cfg.Password)\n        .Build();\n    return await cluster.ConnectAsync(cfg.Keyspace);\n};","handlingStrategy":"validation","validationCode":"options.CreateSessionAsync = async sp =>\n{\n    var cfg = sp.GetRequiredService<IOptions<CassandraConfig>>().Value;\n    var cluster = Cluster.Builder().AddContactPoints(cfg.ContactPoints)\n        .WithCredentials(cfg.User, cfg.Password).Build();\n    var session = await cluster.ConnectAsync(cfg.Keyspace);\n    return session ?? throw new InvalidOperationException(\"session null\");\n};","typeGuard":"static async Task<ISession> NonNullSession(Func<Task<ISession?>> factory) =>\n    await factory() ?? throw new InvalidOperationException(\"session factory returned null\");","tryCatchPattern":"try { await table.InitializeMembershipTable(true); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"is null\"))\n{ logger.LogCritical(ex, \"Cassandra session factory returned null\"); throw; }","preventionTips":["Never return null from CreateSessionAsync","Validate contact points/keyspace/credentials at build time","Throw a descriptive exception inside the factory on failure"],"tags":["cassandra","clustering","config","initialization"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}