{"record":{"id":"2e2076318976558e","repo":"nextauthjs/next-auth","slug":"session-not-found","errorCode":null,"errorMessage":"Session not found","messagePattern":"Session not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-mikro-orm/src/index.ts","lineNumber":194,"sourceCode":"      }\n    },\n    async createSession(data) {\n      const em = await getEM()\n      const user = await em.findOne(UserModel, { id: data.userId })\n      if (!user) throw new Error(\"User not found\")\n      const session = new SessionModel()\n      wrap(session).assign(data)\n      user.sessions.add(session)\n      await em.persistAndFlush(user)\n\n      return wrap(session).toObject()\n    },\n    async updateSession(data) {\n      const em = await getEM()\n      const session = await em.findOne(SessionModel, {\n        sessionToken: data.sessionToken,\n      })\n      if (!session) throw new Error(\"Session not found\")\n      wrap(session).assign(data as object)\n      await em.persistAndFlush(session)\n\n      return wrap(session).toObject()\n    },\n    async deleteSession(sessionToken) {\n      const em = await getEM()\n      const session = await em.findOne(SessionModel, {\n        sessionToken,\n      })\n      if (!session) return null\n      await em.removeAndFlush(session)\n\n      return wrap(session).toObject()\n    },\n    async createVerificationToken(data) {\n      const em = await getEM()\n      const verificationToken = new VerificationTokenModel()","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/adapter-mikro-orm/src/index.ts#L176-L212","documentation":"updateSession looks up the SessionModel by data.sessionToken and throws 'Session not found' when no row matches. Since the adapter requires an existing session, updates against expired, deleted, or nonexistent tokens fail loudly instead of upserting.","triggerScenarios":"Calling updateSession with a sessionToken that was already deleted (logout, expiry cleanup), a token that never existed, or a token stored with different casing/whitespace; also racing deleteSession.","commonSituations":"Stale cookies after a database reset; multiple tabs where one logs out while another refreshes the session; session-expiry cron deleting rows mid-update; manual adapter calls in tests with invented tokens.","solutions":["Check the session exists (getSessionAndUser) before updating, or catch and force re-authentication","Clear stale session cookies so clients stop sending dead tokens","Avoid racing deleteSession against updateSession (dedupe logout flows)","Verify the token value matches exactly what was stored at createSession time"],"exampleFix":"// before\nawait adapter.updateSession({ sessionToken: token, expires: newExpiry })\n// after\nconst session = await adapter.getSessionAndUser(token)\nif (session) {\n  await adapter.updateSession({ sessionToken: token, expires: newExpiry })\n}","handlingStrategy":"try-catch","validationCode":"const existing = await adapter.getSessionAndUser(sessionToken)\nif (!existing) {\n  // clear cookie and force sign-in instead of updating\n}","typeGuard":"function isSessionData(v: unknown): v is { sessionToken: string } {\n  return typeof v === 'object' && v !== null && typeof (v as any).sessionToken === 'string'\n}","tryCatchPattern":"try {\n  await adapter.updateSession({ sessionToken, expires })\n} catch (e) {\n  if ((e as Error).message === 'Session not found') {\n    await signOut({ redirect: false })\n  } else throw e\n}","preventionTips":["Check session existence before updating","Treat 'Session not found' as a logout signal","Avoid concurrent deleteSession/updateSession on the same token","Confirm token values match what createSession stored"],"tags":["mikro-orm","session","not-found","auth"],"backgroundTag":"record-not-found","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}