nextauthjs/next-auth · error
Error updating user: Failed to run the update SQL.
Error message
Error updating user: Failed to run the update SQL.
What it means
updateUser only re-fetches and returns a user when the UPDATE result reports success; if D1 does not report success (or the params shape is missing), the adapter falls through to this error. It means the UPDATE statement itself failed at the driver/batch level rather than returning zero rows.
Source
Thrown at packages/adapter-d1/src/index.ts:218
Object.assign(params, user)
const res = await updateRecord(db, UPDATE_USER_BY_ID_SQL, [
params.name,
params.email,
params.emailVerified?.toISOString(),
params.image,
params.id,
])
if (res.success) {
const user = await getRecord<AdapterUser>(db, GET_USER_BY_ID_SQL, [
params.id,
])
if (user) return user
throw new Error(
"Error updating user: Cannot get user after updating."
)
}
}
throw new Error("Error updating user: Failed to run the update SQL.")
},
async deleteUser(userId) {
// miniflare doesn't support batch operations or multiline sql statements
await deleteRecord(db, DELETE_ACCOUNT_BY_USER_ID_SQL, [userId])
await deleteRecord(db, DELETE_SESSION_BY_USER_ID_SQL, [userId])
await deleteRecord(db, DELETE_USER_SQL, [userId])
return null
},
async linkAccount(a) {
// convert user_id to userId and provider_account_id to providerAccountId
const id = crypto.randomUUID()
const createBindings = [
id,
a.userId,
a.type,
a.provider,
a.providerAccountId,
a.refresh_token,View on GitHub (pinned to a1a16a5a77)
Solutions
- Log/inspect the thrown driver error underneath and confirm the SQL update statement matches your users table columns.
- Ensure params.id is a valid existing user id and the params object only contains AdapterUser fields.
- Run against real D1 or a current miniflare version — old miniflare builds don't support batch operations.
- Update @auth/d1-adapter to the latest version.
Example fix
// before
await adapter.updateUser({ ...user, name: 'new' }) // extra fields may break SQL
// after
await adapter.updateUser({ id: user.id, name: 'new' }) Defensive patterns
Strategy: try-catch
Validate before calling
if (!params?.id) throw new Error('updateUser requires a valid user id')
const existing = await adapter.getUser(params.id)
if (!existing) throw new Error('user does not exist') Type guard
function isValidUpdateParams(p: unknown): p is Partial<AdapterUser> & Pick<AdapterUser, 'id'> {
return !!p && typeof p === 'object' && typeof (p as any).id === 'string'
} Try / catch
try {
await adapter.updateUser(params)
} catch (e) {
if (e instanceof Error && e.message.includes('Failed to run the update SQL')) {
// log the driver error, verify table schema/columns, check D1 status
}
throw e
} Prevention
- Keep updateUser params limited to known AdapterUser columns
- Test updates against real D1, not outdated local miniflare builds
- Keep @auth/d1-adapter up to date for SQL compatibility fixes
- Monitor D1 errors/rate limits in your dashboard
When it happens
Trigger: adapter.updateUser(params) where the D1 batch result's success flag is false — malformed SQL, wrong binding types, D1 API errors, or params lacking a valid id so the generated UPDATE is invalid.
Common situations: Passing an AdapterUser whose extra fields don't match table columns, D1 outages/rate limits, older adapter versions generating SQL incompatible with current D1, or miniflare lacking batch support (see the comment in deleteUser).
Related errors
- Error creating user: Cannot get user after creation.
- Error updating user: Cannot get user after updating.
- Couldn't create session
- No user found.
- Authenticator not found.
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/3ffa760b21038fff.
Report an issue: GitHub.