nextauthjs/next-auth · error

[updateUser] Failed to fetch updated user

Error message

[updateUser] Failed to fetch updated user

What it means

After merging the partial user into Firestore with userRef.set(partialUser, { merge: true }), the adapter reads the document back and throws '[updateUser] Failed to fetch updated user' if the read returns nothing. Since a set with merge should always leave a readable doc, this signals the document disappeared between write and read or the read helper misreports the result.

Source

Thrown at packages/adapter-firebase/src/index.ts:136

      const account = await getOneDoc(
        C.accounts
          .where("provider", "==", provider)
          .where(mapper.toDb("providerAccountId"), "==", providerAccountId)
      )
      if (!account) return null

      return await getDoc(C.users.doc(account.userId))
    },

    async updateUser(partialUser) {
      if (!partialUser.id) throw new Error("[updateUser] Missing id")

      const userRef = C.users.doc(partialUser.id)

      await userRef.set(partialUser, { merge: true })

      const user = await getDoc(userRef)
      if (!user) throw new Error("[updateUser] Failed to fetch updated user")

      return user
    },

    async deleteUser(userId) {
      await db.runTransaction(async (transaction) => {
        const accounts = await C.accounts
          .where(mapper.toDb("userId"), "==", userId)
          .get()
        const sessions = await C.sessions
          .where(mapper.toDb("userId"), "==", userId)
          .get()

        transaction.delete(C.users.doc(userId))

        accounts.forEach((account) => transaction.delete(account.ref))
        sessions.forEach((session) => transaction.delete(session.ref))
      })

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Audit Firestore triggers/extensions on the users collection that might delete or restrict the doc right after writes.
  2. Fix the custom getDoc helper to honor snapshot existence and return mapped data correctly.
  3. Verify security rules permit read access for the adapter's credentials on the users collection.
  4. Serialize user-deletion and user-update flows to avoid the delete/update race.

Example fix

// before
await userRef.set(partialUser, { merge: true })
const user = await getDoc(userRef)
if (!user) throw new Error('[updateUser] Failed to fetch updated user')
// after
await userRef.set(partialUser, { merge: true })
const snap = await userRef.get()
if (!snap.exists) throw new Error('[updateUser] Failed to fetch updated user')
const user = mapper.fromDb({ id: snap.id, ...snap.data() })
Defensive patterns

Strategy: try-catch

Validate before calling

const before = await userRef.get()
if (!before.exists) throw new Error(`User doc ${partialUser.id} missing before update`)

Type guard

function isPopulatedDoc<T>(d: T | undefined | null): d is T {
  return d !== undefined && d !== null
}

Try / catch

try {
  await adapter.updateUser({ id, ...patch })
} catch (e) {
  if ((e as Error).message.includes('Failed to fetch updated user')) {
    console.warn(`Update on ${id} succeeded but readback failed; check triggers/rules`)
    return
  }
  throw e
}

Prevention

When it happens

Trigger: A Firestore security rule, extension, or Cloud Function (e.g. onWrite cleanup) removes/locks the document immediately after the merge; a custom getDoc wrapper returns undefined despite doc existence; concurrent deleteUser racing the update.

Common situations: Delete-user Cloud Functions triggered by auth user deletion that also purge Firestore docs while a session update is in flight; rules denying the follow-up read for the adapter's identity; emulator restarts losing data mid-test.

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/3f8bfeaa2b3474b2. Report an issue: GitHub.