nextauthjs/next-auth · error

Error updating user: Cannot get user after updating.

Error message

Error updating user: Cannot get user after updating.

What it means

updateUser runs the UPDATE SQL, and when it reports success it immediately re-selects the user by id; if that SELECT returns nothing the adapter throws this error. It indicates the update claimed success but the row cannot be read back, so the adapter will not fabricate a user object.

Source

Thrown at packages/adapter-d1/src/index.ts:213

        user.id,
      ])
      if (params) {
        // copy any properties not in the update into the existing one and use that for bind params
        // covers the scenario where the user arg doesnt have all of the current users properties
        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,

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Confirm a user with that id actually exists (SELECT it manually or via getUser(id)) before updating.
  2. Verify the D1 binding points at the database containing the users table.
  3. Check that the users table schema matches the adapter's expected SQL (column names, primary key on id).
  4. Upgrade the adapter package to get the latest D1 batch/SQL fixes.

Example fix

// before
await adapter.updateUser({ id: maybeId, email: newEmail })
// after
const existing = await adapter.getUser(maybeId)
if (!existing) throw new Error(`No user with id ${maybeId}`)
await adapter.updateUser({ id: maybeId, email: newEmail })
Defensive patterns

Strategy: validation

Validate before calling

const user = await adapter.getUser(id)
if (!user) throw new Error(`Cannot update: no user with id ${id}`)

Type guard

function hasUserId(u: Partial<AdapterUser>): u is Partial<AdapterUser> & Pick<AdapterUser, 'id'> {
  return typeof u.id === 'string' && u.id.length > 0
}

Try / catch

try {
  const updated = await adapter.updateUser({ id, ...changes })
} catch (e) {
  if (e instanceof Error && e.message.includes('Cannot get user after updating')) {
    // re-fetch via getUser(id); if missing, the row was deleted concurrently
  }
  throw e
}

Prevention

When it happens

Trigger: adapter.updateUser({ id, ... }) where res.success is true but GET_USER_BY_ID_SQL finds no row for params.id — e.g. updating a user id that does not exist in the users table, or schema/column mismatches making the read fail.

Common situations: Stale user id from a deleted row, updating a user created outside this adapter with a different id format, custom table schema, or D1 binding pointing at a different database than the one that holds the user.

Related errors


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