Cannot begin a transaction on a closed session

Hi All,

I am writing an insert operation into neo4j using neo4j driver for Node js. The first time, the function will run, and on calling the same function second time, it will throw error " Cannot begin a transaction on a closed session."

Here is the code snippet

let query='some query';
let param ={ some param};
try{
await session.writeTransaction( async txc =>{

       let result = await txc.run(query, param)
     
       if (result.records.length != 0) {
           console.log('operation is successful')
       } else {
       console.log('operation return nothing')

      }
   })      

} catch (error){
console.log('exception occure', error)
throw error
}finally{

   await session.close()

}

I have noticed, in finally I am closing the session, would that be an issue. If yes, then when to close the session and when to start a session?

Hi,
The code you show doesn't actually display how the second query is coming through or instantiated.

Typically, you will want to create a new session within the same code execution as the query and the close statements. A typical workflow would be something like this...

Enter Function/Method
Create Session object
Run query(s) against Session object
Close Session object
Return from function method

The answer to that question is in when and where session is created and connected.

Under the hood, the Neo4j API provides a service for interacting with the database, with which transaction instances are created. Each transaction runs one and only one set of operations, then closes.

servicetransaction → command.

In the javascript driver, session is both a Promise, and an abstraction for the Neo4j service. That makes things a little more tricky if you're trying to create persistent objects, or make multiple async calls to a single instance of a thing which uses session.

First, I'd take a close look at the example from github:neo4j\neo4j-javascript-driver.

You'll need to close the session to resolve the promise which completes the transaction. Thus you'll need to create a new session on subsequent calls to the same code.

Rather than directly managing the transactions, I would advise trying to keep to the promise pattern in the example if you can.

1 Like

Thanks its solved the problem, i had created another file as config file, where i has inititalise graph db configuration.

image

So instead of exporting driver, i had created a session object const session = driver.session() and exported it.

So whenever my method was called, session was the old one, so it was throwing error.

import driver from './config'
async functionName(arg1, arg2) {

const session = driver.session()


let query;

  query = `create (p:Person{id:$arg1, name:$arg2}) return p`
}

let param = {
  id:arg1,
  name: arg2

}


try{
 await session.writeTransaction( async txc =>{

       let result = await txc.run(query, param)
    
       if (result.records.length != 0) {
           console.log('operation is successful')
       } else {
       
 console.log('query resturn nothing')
      }
   })

}catch(error){
console.log('exception occure', error)
throw error
}finally{

 await session.close()

}

}

1 Like

Hi, I found you have to always instantiate a new session, just like you said, but you also have to do:

let result = await driver.session()
...
await session.close()

Here's a working snippet:

Execute Raw Queries here
async function executeCypherQuery(statement, params = {}) {
  try {
    let session = driver.session()
    const result = await session.run(statement, params);
    await session.close();
    return result;
  } catch (error) {
    throw error; // we are logging this error at the time of calling this method
  }
}