Neo4jClient: ObjectDisposedException: Cannot open a new session on a driver that is already disposed. Object name: 'Driver'. or Object name: 'ConnectionPool'.

Describe the bug Having lots of issues related to connection. Cannot open a new session on a driver that is already disposed.

Versions:

  • Neo4jClient 4.1.5
  • Bolt or Http BoltGraphClient
  • .NET Version 5 (ASP.Net / Blazor server-side)
  • Server Version neo4j Community 4.1.6
  • Using neo4j+s:// protocol

To Reproduce I have a static IGraphClient c; that is instantiated to a BoltGraphClient

After some seconds I instantiate a new BoltGraphClient and assign to c
“Randomly” (Thread related?) I get this error when trying to use this connection :

An unhandled exception occurred while processing the request.
ObjectDisposedException: Failed to acquire a new connection as the driver has already been disposed.
Object name: 'ConnectionPool'.

ObjectDisposedException: Failed to acquire a new connection as the driver has already been disposed. Object name: 'ConnectionPool'.

ObjectDisposedException: Cannot open a new session on a driver that is already disposed.
Object name: 'Driver'.

Neo4j.Driver.Internal.Driver.ThrowDriverClosedException()
Neo4j.Driver.Internal.Driver.Session(Action<SessionConfigBuilder> action, bool reactive)
Neo4j.Driver.Internal.Driver.AsyncSession(Action<SessionConfigBuilder> action)
Neo4jClient.BoltGraphClient.Neo4jClient.IRawGraphClient.ExecuteGetCypherResultsAsync<TResult>(CypherQuery query)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 22 (12 by maintainers)

Most upvoted comments

awesome!

Definitely reopen if you need more work on it!

Hey @TonyHenrique

How is this going?

Chris

There is only one point in the client where the Driver is disposed - here - so if your code is calling Dispose on your client instance, that is the only point where the Neo4jClient code is calling it.

Obviously you can call Dispose on the .Driver property directly which would also elicit this error message. I would strongly recommend you remove any code that is doing this, you do not need to manage the Driver, and it’ll make debugging a lot easier if we only have one thing to worry about. If that is the case then we’re in a good place.

In terms of debugging this - you’ll probably find that a log message when you create/dispose of the client will show some race conditions. Are you using the client within a using anywhere? In theory if you’re using the DI from the framework - you don’t need to care about the disposal at all - that’ll handle it all.

Another thought could be that the testing framework might be terminating a request early, and due to async-ness the session is ended whilst another thread is starting up a query.

As a side note - instead of tearing down the whole client / driver yourself, you can also call ConnectAsync again - which will redo the Driver for you.

NB. It’s not because it’s static per se, but because it’s static in a web scenario, where your sessions will tidy themselves up

But you’re still storing it in a static variable - that’s the problem - if you’re injecting it - you shouldn’t be doing that.

Ok, does the Blazor app have a startup.cs file? I’m not sure of the standard layout - but most of these default things from MS have IOC/DI things built in - and I really think that’s where this is coming from.

Static members in a web app are super scary as they are shared by all the sessions - and that means the whole lifecycle, and it’s possible that one session is finishing as another starts, disposes and causes this.

I think you’re going to need to provide some sort of working example of this, I’ve tried the code below, but I don’t get the error - but that’s not necessarily unexpected. If you can do it in LinqPad - the attached file will give you a template with Neo4jClient ready to go.

Empty-Neo4jClient.zip

static IGraphClient _client;

async Task Main()
{
	var client = new BoltGraphClient("neo4j://localhost:7687", "neo4j", "neo");
	client.DefaultDatabase = "paysim";
	await client.ConnectAsync();
	
	_client = client;	
	await Execute();
	
	Console.WriteLine("Waiting...");
	await Task.Delay(TimeSpan.FromMinutes(6));
	Console.WriteLine("Carrying on");
	
	var c2 = new BoltGraphClient("neo4j://localhost:7687", "neo4j", "neo");
	c2.DefaultDatabase = "paysim";
	await c2.ConnectAsync();
	
	_client = c2;	
	await Execute();
}

public async Task Execute(){
	(await _client.Cypher.Match("(n)").Return (n => n.Count()).ResultsAsync).Dump();
}