nextauthjs/next-auth · error
No user id.
Error message
No user id.
What it means
The MySQL drizzle adapter's updateUser requires data.id to locate the row to update and throws this error when id is missing. updateUser in Auth.js always supplies an id, so this usually means updateUser was called directly with a partial user object lacking id.
Source
Thrown at packages/adapter-drizzle/src/lib/mysql.ts:213
.then((res) => res[0])
},
async getSessionAndUser(sessionToken: string) {
return client
.select({
session: sessionsTable,
user: usersTable,
})
.from(sessionsTable)
.where(eq(sessionsTable.sessionToken, sessionToken))
.innerJoin(usersTable, eq(usersTable.id, sessionsTable.userId))
.then((res) => (res.length > 0 ? res[0] : null)) as Awaitable<{
session: AdapterSession
user: AdapterUser
} | null>
},
async updateUser(data: Partial<AdapterUser> & Pick<AdapterUser, "id">) {
if (!data.id) {
throw new Error("No user id.")
}
await client
.update(usersTable)
.set(data)
.where(eq(usersTable.id, data.id))
const [result] = await client
.select()
.from(usersTable)
.where(eq(usersTable.id, data.id))
if (!result) {
throw new Error("No user found.")
}
return result as Awaitable<AdapterUser>
},View on GitHub (pinned to a1a16a5a77)
Solutions
- Always include id: adapter.updateUser({ id, ...changes }).
- Validate the id exists before calling updateUser.
- If updating by email, first getUserByEmail then use the returned user's id.
Example fix
// before
await adapter.updateUser({ email: 'new@mail.com' })
// after
const user = await adapter.getUserByEmail('new@mail.com')
await adapter.updateUser({ id: user.id, email: 'new@mail.com' }) Defensive patterns
Strategy: validation
Validate before calling
if (!data.id) throw new Error('updateUser requires an id') Type guard
function hasId(u: Partial<AdapterUser>): u is Partial<AdapterUser> & Pick<AdapterUser, 'id'> {
return typeof u.id === 'string' && u.id.length > 0
} Try / catch
try {
await adapter.updateUser(data)
} catch (e) {
if (e instanceof Error && e.message === 'No user id.') {
// resolve the id via getUserByEmail/getUserByAccount, then retry
}
throw e
} Prevention
- Never call updateUser without an id in the payload
- Resolve ids via getUserByEmail/getUserByAccount when only email/account is known
- Type your update payloads as Partial<AdapterUser> & Pick<AdapterUser, 'id'>
- Validate inputs at the edge before they reach the adapter
When it happens
Trigger: Calling adapter.updateUser({ email: 'x' }) without an id property, or id present but undefined due to destructuring/spread of a partial object.
Common situations: Custom code calling the adapter directly, building the update object dynamically and dropping id, or integrating with a framework that passes Partial<AdapterUser>.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- No user found.
- Error updating user: Cannot get user after updating.
- Unsupported database type (${typeof db}) in Auth.js Drizzle
- Authenticator not found.
- No user id.
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/f5e557ddbe4b680c.
Report an issue: GitHub.