nextauthjs/next-auth · error

Session not found

Error message

Session not found

What it means

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.

Source

Thrown at packages/adapter-mikro-orm/src/index.ts:194

      }
    },
    async createSession(data) {
      const em = await getEM()
      const user = await em.findOne(UserModel, { id: data.userId })
      if (!user) throw new Error("User not found")
      const session = new SessionModel()
      wrap(session).assign(data)
      user.sessions.add(session)
      await em.persistAndFlush(user)

      return wrap(session).toObject()
    },
    async updateSession(data) {
      const em = await getEM()
      const session = await em.findOne(SessionModel, {
        sessionToken: data.sessionToken,
      })
      if (!session) throw new Error("Session not found")
      wrap(session).assign(data as object)
      await em.persistAndFlush(session)

      return wrap(session).toObject()
    },
    async deleteSession(sessionToken) {
      const em = await getEM()
      const session = await em.findOne(SessionModel, {
        sessionToken,
      })
      if (!session) return null
      await em.removeAndFlush(session)

      return wrap(session).toObject()
    },
    async createVerificationToken(data) {
      const em = await getEM()
      const verificationToken = new VerificationTokenModel()

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Check the session exists (getSessionAndUser) before updating, or catch and force re-authentication
  2. Clear stale session cookies so clients stop sending dead tokens
  3. Avoid racing deleteSession against updateSession (dedupe logout flows)
  4. Verify the token value matches exactly what was stored at createSession time

Example fix

// before
await adapter.updateSession({ sessionToken: token, expires: newExpiry })
// after
const session = await adapter.getSessionAndUser(token)
if (session) {
  await adapter.updateSession({ sessionToken: token, expires: newExpiry })
}
Defensive patterns

Strategy: try-catch

Validate before calling

const existing = await adapter.getSessionAndUser(sessionToken)
if (!existing) {
  // clear cookie and force sign-in instead of updating
}

Type guard

function isSessionData(v: unknown): v is { sessionToken: string } {
  return typeof v === 'object' && v !== null && typeof (v as any).sessionToken === 'string'
}

Try / catch

try {
  await adapter.updateSession({ sessionToken, expires })
} catch (e) {
  if ((e as Error).message === 'Session not found') {
    await signOut({ redirect: false })
  } else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/2e2076318976558e. Report an issue: GitHub.