next-auth: Neo4j session error (GetSessionAndUserError)
Adapter type
Environment
System: OS: macOS 13.0 CPU: (16) x64 Intel® Core™ i9-9880H CPU @ 2.30GHz Memory: 317.06 MB / 16.00 GB Shell: 3.2.57 - /bin/bash
Binaries: Node: 18.12.1 - /usr/local/opt/node@18/bin/node Yarn: 1.22.11 - /usr/local/bin/yarn npm: 8.19.2 - /usr/local/opt/node@18/bin/npm
Browsers: Chrome: 107.0.5304.110 Firefox: 101.0 Safari: 16.1
npmPackages: next: 13.0.4 => 13.0.4 next-auth: ^4.16.4 => 4.16.4 react: 18.2.0 => 18.2.0 neo4j-driver: ^5.2.0 swr: ^1.3.0 typescript: 4.9.3
npmPackages: @next-auth/neo4j-adapter: ^1.0.5 => 1.0.5
Reproduction URL
https://github.com/vladutilie/issue-next-auth-neo4j
Describe the issue
Hello,
Vlad here, a Next.js and awesome-packages-related fan, enthusiast 😎 and hopefully a contributor to this community.
Since I’ve started to use Neo4j as Adapter for my NextAuth implementation, I got this error in logs and the client cannot get API responses if the focus of the page is lost. I’m using SWR to call an API endpoint which is using the unstable_getServerSession
function to check if the user is authenticated.
Long story short
🍀 I start the server, I open the page (let’s say I’m authenticated) and all data from my API (fetched with SWR) is in place. I browse my page and so on, and all is perfect.
🍎 The issue occurs when I click on another tab (or just I open a new one), browse there for some seconds, and then come back to my initial tab - this will trigger SWR to revalidate (re-fetch) the date. The SWR fetch fails because the unstable_getServerSession
function returns null 🤷🏻♂️ and at the same time I get the following error.
The error I got
The error I got in VS code logs is the following:
[next-auth][error][adapter_error_getSessionAndUser]
https://next-auth.js.org/errors#adapter_error_getsessionanduser You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session. {
message: 'You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session.',
stack: 'Neo4jError: You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session.\n' +
' at new Neo4jError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:77:16)\n' +
' at newError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:113:12)\n' +
' at Session._beginTransaction (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:280:40)\n' +
' at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:394:77\n' +
' at TransactionExecutor.<anonymous> (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:116:46)\n' +
' at step (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:52:23)\n' +
' at Object.next (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:33:53)\n' +
' at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:27:71\n' +
' at new Promise (<anonymous>)\n' +
' at __awaiter (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:23:12)',
name: 'Neo4jError'
}
[next-auth][error][SESSION_ERROR]
https://next-auth.js.org/errors#session_error You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session. Neo4jError: You cannot begin a transaction on a session with an open transaction; either run from within the transaction or use a different session.
at new Neo4jError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:77:16)
at newError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:113:12)
at Session._beginTransaction (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:280:40)
at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:394:77
at TransactionExecutor.<anonymous> (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:116:46)
at step (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:52:23)
at Object.next (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:33:53)
at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:27:71
at new Promise (<anonymous>)
at __awaiter (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:23:12) {
name: 'GetSessionAndUserError',
code: 'N/A'
}
What I have tried?
I have tried to call session.close()
in node_modules/@next-auth/neo4j-adapter/dist/utils.js
like below, hoping for an eventually fix, but it was in vain:
function client(session) {
return {
/** Reads values from the database */
async read(statement, values) {
var _a, _b;
const result = await session.readTransaction((tx) => tx.run(statement, values));
session.close(); // 👈
return (_b = exports.format.from((_a = result === null || result === void 0 ? void 0 : result.records[0]) === null || _a === void 0 ? void 0 : _a.get(0))) !== null && _b !== void 0 ? _b : null;
},
/**
* Reads/writes values from/to the database.
* Properties are available under `$data`
*/
async write(statement, values) {
var _a;
const result = await session.writeTransaction((tx) => tx.run(statement, { data: exports.format.to(values) }));
session.close(); // 👈
return exports.format.from((_a = result === null || result === void 0 ? void 0 : result.records[0]) === null || _a === void 0 ? void 0 : _a.toObject());
},
};
}
The error I got after my try
Cannot begin a transaction on a closed session. 🤦♂️
[next-auth][error][adapter_error_getSessionAndUser]
https://next-auth.js.org/errors#adapter_error_getsessionanduser Cannot begin a transaction on a closed session. {
message: 'Cannot begin a transaction on a closed session.',
stack: 'Neo4jError: Cannot begin a transaction on a closed session.\n' +
' at new Neo4jError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:77:16)\n' +
' at newError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:113:12)\n' +
' at Session._beginTransaction (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:277:40)\n' +
' at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:394:77\n' +
' at TransactionExecutor.<anonymous> (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:116:46)\n' +
' at step (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:52:23)\n' +
' at Object.next (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:33:53)\n' +
' at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:27:71\n' +
' at new Promise (<anonymous>)\n' +
' at __awaiter (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:23:12)',
name: 'Neo4jError'
}
[next-auth][error][SESSION_ERROR]
https://next-auth.js.org/errors#session_error Cannot begin a transaction on a closed session. Neo4jError: Cannot begin a transaction on a closed session.
at new Neo4jError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:77:16)
at newError (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/error.js:113:12)
at Session._beginTransaction (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:277:40)
at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/session.js:394:77
at TransactionExecutor.<anonymous> (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:116:46)
at step (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:52:23)
at Object.next (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:33:53)
at /Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:27:71
at new Promise (<anonymous>)
at __awaiter (/Users/vlad/www/issue-next-auth-neo4j/node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:23:12) {
name: 'GetSessionAndUserError',
code: 'N/A'
}
So I came here for another perspective. 🎩 Of course, I’m willing to help, just let me know how 😇.
How to reproduce
- Clone the repository: https://github.com/vladutilie/issue-next-auth-neo4j
- Run
$ yarn install
- Run
$ cp .env.example .env
- Set up the fields in
.env
file (you will need a Neo4j database instance - I’m using Neo4j Desktop for local development but you can use an AuraDB or something similar as well) - Run
$ npm run dev
in terminal - Open the link http://localhost:3000/api/auth/signin in Chrome or Firefox, put your email and authenticate yourself
- You will see a text like this on the page:
{"user":{"email":"you@email.com"},"expires":"2022-12-18T20:12:48.651Z"}
- Open a new tab in the browser and access a random page - this will trigger losing focus of the current page and will make SWR revalidate (re-fetch) the data from the API (
/api/hello
endpoint in this case) - Click back on the initial tab after a few seconds
- You will see the text
{"message":"Not authenticated."}
in the page - Go into your logs and you will see the error described above.
Expected behavior
After the 9th step from reproduction, on the page you should see the same text you saw first, something like {"user":{"email":"you@email.com"},"expires":"2022-12-18T20:12:48.651Z"}
and the logs should not have that error, so the unstable_getServerSession
function should return the authenticated user data.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 2
- Comments: 18
@balazsorban44 @ndom91 Hi, I need some advice on my approaach to fix this, please.
It looks 2 (or more) adapter functions are running at the same time. Looking at the bug report I think
getSessionAndUser
is being run while still in the middle of a current adapter function.I’ve checked (the neo4j adapter)[https://github.com/nextauthjs/next-auth/blob/main/packages/adapter-neo4j/src/index.ts] and all functions are async and have the correct await.
I think that
unstable_getServerSession
or some other part of core next-auth is not awaiting the return value of adapter functions. Hence allowing 2 to be run at the same time, causing the error.I can see 2 approaches to a fix:
Do you think my diagnosis is right? I can implement the neo4j-adapter change, plase advise.
Hey @vladutilie sorry i can’t dedicate a bunch of time to help but I can give some pointers.
I’ve seen it often before and it can most easilly be replicated by starting a neo4j session from the driver. Then closing with session.close() then attempting to read or write from the database with the closed session.I have this adapter runing in production with pinned slightly old versions and jwt (not using unstable_getServerSession).
I suspect the error you’re seeing is because of some new feature or change (to this package or other dependancy) since the neo4j adapter was written.
Sorry I can’t assingn myself to fix this right now, my work load is huge. Regardless, let me know how you get on.
Running into the same problem
Hi @vladutilie could you try with neo4j-driver 4.x ?
It seems 5 was only rolled out a few months ago and the neo4j adapret is tested up to version 4.
This way at least we will know how to proceeed, additional tests/amends for v5 or futher investigation elsewhere.
FYI this error does not pop up on Vercel functions, so it verifies the hypothesis