nextauthjs/next-auth · error
User not found.
Error message
User not found.
What it means
The SQLite Drizzle adapter's updateUser runs UPDATE ... WHERE id = ? RETURNING().get(). If .get() returns undefined, the WHERE clause matched no row, so the user with that id does not exist and the adapter throws 'User not found.'
Source
Thrown at packages/adapter-drizzle/src/lib/sqlite.ts:204
return result as Awaitable<{
session: AdapterSession
user: AdapterUser
} | null>
},
async updateUser(data: Partial<AdapterUser> & Pick<AdapterUser, "id">) {
if (!data.id) {
throw new Error("No user id.")
}
const result = await client
.update(usersTable)
.set(data)
.where(eq(usersTable.id, data.id))
.returning()
.get()
if (!result) {
throw new Error("User not found.")
}
return result as Awaitable<AdapterUser>
},
async updateSession(
data: Partial<AdapterSession> & Pick<AdapterSession, "sessionToken">
) {
const result = await client
.update(sessionsTable)
.set(data)
.where(eq(sessionsTable.sessionToken, data.sessionToken))
.returning()
.get()
return result ?? null
},
async linkAccount(data: AdapterAccount) {
await client.insert(accountsTable).values(data).run()View on GitHub (pinned to a1a16a5a77)
Solutions
- Call getUser(id) first and only update when the user exists.
- Confirm the Drizzle SQLite client uses the expected database file (check the db filename/connection per environment).
- Ensure the id value's type matches how it was stored (consistent string uuids recommended).
- If users are being deleted elsewhere, handle the not-found case in your flow instead of blindly updating.
Example fix
// before
await adapter.updateUser({ id: staleId, name: 'New' })
// after
const user = await adapter.getUser(staleId)
if (!user) {
console.warn('User vanished, skipping update', staleId)
return
}
await adapter.updateUser({ id: user.id, name: 'New' }) Defensive patterns
Strategy: validation
Validate before calling
const existing = await adapter.getUser(id)
if (!existing) throw new Error(`No SQLite user with id ${id}`)
await adapter.updateUser({ id, ...patch }) Try / catch
try {
await adapter.updateUser({ id, ...patch })
} catch (e) {
if ((e as Error).message === 'User not found.') {
console.warn(`User ${id} missing in SQLite; skipping update`)
return null
}
throw e
} Prevention
- Confirm the Drizzle SQLite client file path matches the environment (dev/test/prod db files).
- Use consistent id types (string uuids) to avoid SQLite type-affinity mismatch on eq().
- Re-fetch users after any database reset or reseed instead of caching stale ids.
When it happens
Trigger: updateUser({ id: someId, ... }) where no row in the SQLite users table has that id — deleted user, wrong DB file, or id type mismatch (e.g. number vs string in SQLite).
Common situations: SQLite file path differences between environments (dev db vs test db) so the id exists in one but not the other; resetting the database file while holding stale session/user ids; SQLite flexible-mode type affinity causing '1' vs 1 id mismatches.
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/5da50ac8b981aafe.
Report an issue: GitHub.