You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
csmcallister opened this issue
Feb 6, 2024
· 0 comments
· May be fixed by #9934
Labels
adaptersChanges related to the core code concerning database adaptersbugSomething isn't workingtriageUnseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
This is related to #5849, but perhaps distinct because it's occurring with @auth/neo4j-adapter and next-auth 5 (beta). After cloning the example app and adding in the neo4j adapter, I am able to login (using Google as a provider) and hit each of the example pages (RSC, client, protected API and middleware) to see that I'm successfully logged in. However, both the client and RSC pages raise the following error:
[auth][error] AdapterError: Read more at https://errors.authjs.dev#adaptererror
[auth][cause]: 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 (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/error.js:74:16)
at newError (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/error.js:106:12)
at Session._beginTransaction (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/session.js:404:40)
at eval (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/session.js:531:26)
at TransactionExecutor.eval (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:280:37)
at step (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:117:23)
at Object.eval [as next] (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:58:20)
at eval (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:36:71)
at new Promise (<anonymous>)
at __awaiter (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:18:12)
at TransactionExecutor._executeTransactionInsidePromise (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:268:16)
at eval (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:230:19)
at new Promise (<anonymous>)
at TransactionExecutor.execute (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:229:16)
at Session._runTransaction (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/session.js:530:42)
at Session.writeTransaction (webpack-internal:///(rsc)/./node_modules/neo4j-driver-core/lib/session.js:526:21)
at write (webpack-internal:///(rsc)/./node_modules/@auth/neo4j-adapter/index.js:293:42)
at getSessionAndUser (webpack-internal:///(rsc)/./node_modules/@auth/neo4j-adapter/index.js:203:34)
at acc.<computed> (webpack-internal:///(rsc)/./node_modules/@auth/core/lib/init.js:170:30)
at Module.session (webpack-internal:///(rsc)/./node_modules/@auth/core/lib/actions/session.js:84:36)
at AuthInternal (webpack-internal:///(rsc)/./node_modules/@auth/core/lib/index.js:50:77)
at async Auth (webpack-internal:///(rsc)/./node_modules/@auth/core/index.js:123:29)
at async UserButton (webpack-internal:///(rsc)/./components/user-button.tsx:19:21)
[auth][details]: {}
As you can see, const session = await auth() in UserButton is causing the error. This is because const session = await auth() is also called within app/server-example/page.tsx as well as app/client-example/page.tsx. Comment out either of those calls in the pages, so that there's just one const session = await auth() occurring, and the error disappears. Only problem is, I'd like to be able to call const session = await auth() in both UserButton.tsx as well as within my pages. As the error message states, there's an issue with the session lifecycle within the Neo4jAdapter. As the neo4j docs state, "Session creation is a lightweight operation, so sessions can be created and destroyed without significant cost. Always close sessions when you are done with them.".
I suspected the session wasn't being closed and then recreated since the adapter is passed in as Neo4jAdapter(session) instead of as Neo4jAdapter(driver). Looking into node_modules/@auth/neo4j-adapter/index.js, I could see this is the case:
Above, the session is passed to the client function, which manages the transactions. However, the session never gets closed. Editing the .js code locally, I was able to resolve the error by:
Making the driver the argument to Neo4jAdapter (i.e., export function Neo4jAdapter(session) becomes export function Neo4jAdapter(driver))
Updating auth.ts to pass the driver to Neo4jAdapter:
exportconstconfig={theme: {logo: "https://next-auth.js.org/img/logo/logo-sm.png",},adapter: Neo4jAdapter(driver)// <--- here
Updating the client function to accept the driver instead of a session as its argument. That way we can create new lightweight sessions with each read/write transaction. I also ensured that the read and write functions close the session:
functionclient(driver){return{/** Reads values from the database */asyncread(statement,values){constsession=driver.session()try{constresult=awaitsession.executeRead((tx)=>tx.run(statement,values));returnformat.from(result?.records[0]?.get(0))??null;}finally{session.close();}},/** * Reads/writes values from/to the database. * Properties are available under `$data` */asyncwrite(statement,values){constsession=driver.session()try{constresult=awaitsession.executeWrite((tx)=>tx.run(statement,{data: format.to(values)}));returnformat.from(result?.records[0]?.toObject());}finally{session.close();}},};}
Note that I also replaced writeTransaction and readTransaction with executeWrite and executeRead, respectively, since the former methods are marked for deprecation. The difference is immaterial to this bug.
Scope down instantiation the read/write functions within Neo4jAdapter, e.g.,
exportfunctionNeo4jAdapter(driver){return{asynccreateUser(data){const{ write }=client(driver)// scope client (and session) instantiation to each adapter methodconstuser={ ...data,id: crypto.randomUUID()};awaitwrite(`CREATE (u:User $data)`,user);returnuser;},asyncgetUser(id){const{ read }=client(driver)// scope client (and session) instantiation to each adapter methodreturnawaitread(`MATCH (u:User { id: $id }) RETURN u{.*}`,{
id,});},
...
After doing the above (don't forget to rm -rf .next when running the dev server to see these effects in action), the error message goes away and the demo app runs swimmingly.
How to reproduce
See the linked repo. It will demonstrate the bug and you can modify the adapter library within node_modules as documented above to resolve it.
Expected behavior
The adapter doesn't throw this error.
The text was updated successfully, but these errors were encountered:
csmcallister
added
adapters
Changes related to the core code concerning database adapters
bug
Something isn't working
triage
Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
labels
Feb 6, 2024
csmcallister
added a commit
to csmcallister/next-auth
that referenced
this issue
Feb 6, 2024
…antiating Neo4jAdapter nextauthjs#9933
By making the neo4j driver as opposed to a single session the argument for Neo4jAdapter, we can ensure each database transaction has its own session and avoid race conditions where a transaction occurs while another, past transaction is still open.
adaptersChanges related to the core code concerning database adaptersbugSomething isn't workingtriageUnseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Adapter type
@auth/neo4j-adapter
Environment
System:
OS: Linux 5.15 Ubuntu 22.04.3 LTS 22.04.3 LTS (Jammy Jellyfish)
CPU: (12) x64 AMD Ryzen 5 3600X 6-Core Processor
Memory: 13.23 GB / 15.58 GB
Container: Yes
Shell: 5.1.16 - /bin/bash
Binaries:
Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node
npm: 10.2.4 - ~/.nvm/versions/node/v20.11.0/bin/npm
pnpm: 8.15.1 - ~/.nvm/versions/node/v20.11.0/bin/pnpm
npmPackages:
@auth/neo4j-adapter: ^1.3.1 => 1.3.1
next: ^14.1.0 => 14.1.0
next-auth: beta => 5.0.0-beta.5
react: ^18.2.0 => 18.2.0
Reproduction URL
https://github.com/csmcallister/next-auth-example-neo4j-adapter-bug
Describe the issue
This is related to #5849, but perhaps distinct because it's occurring with
@auth/neo4j-adapter
andnext-auth
5 (beta). After cloning the example app and adding in the neo4j adapter, I am able to login (using Google as a provider) and hit each of the example pages (RSC, client, protected API and middleware) to see that I'm successfully logged in. However, both the client and RSC pages raise the following error:As you can see,
const session = await auth()
inUserButton
is causing the error. This is becauseconst session = await auth()
is also called withinapp/server-example/page.tsx
as well asapp/client-example/page.tsx
. Comment out either of those calls in the pages, so that there's just oneconst session = await auth()
occurring, and the error disappears. Only problem is, I'd like to be able to callconst session = await auth()
in bothUserButton.tsx
as well as within my pages. As the error message states, there's an issue with the session lifecycle within the Neo4jAdapter. As the neo4j docs state, "Session creation is a lightweight operation, so sessions can be created and destroyed without significant cost. Always close sessions when you are done with them.".I suspected the session wasn't being closed and then recreated since the adapter is passed in as
Neo4jAdapter(session)
instead of asNeo4jAdapter(driver)
. Looking intonode_modules/@auth/neo4j-adapter/index.js
, I could see this is the case:Above, the session is passed to the
client
function, which manages the transactions. However, the session never gets closed. Editing the.js
code locally, I was able to resolve the error by:Neo4jAdapter
(i.e.,export function Neo4jAdapter(session)
becomesexport function Neo4jAdapter(driver)
)auth.ts
to pass the driver toNeo4jAdapter
:read
andwrite
functions close the session:After doing the above (don't forget to
rm -rf .next
when running the dev server to see these effects in action), the error message goes away and the demo app runs swimmingly.How to reproduce
See the linked repo. It will demonstrate the bug and you can modify the adapter library within node_modules as documented above to resolve it.
Expected behavior
The adapter doesn't throw this error.
The text was updated successfully, but these errors were encountered: