{"record":{"id":"3f8bfeaa2b3474b2","repo":"nextauthjs/next-auth","slug":"updateuser-failed-to-fetch-updated-user","errorCode":null,"errorMessage":"[updateUser] Failed to fetch updated user","messagePattern":"\\[updateUser\\] Failed to fetch updated user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-firebase/src/index.ts","lineNumber":136,"sourceCode":"      const account = await getOneDoc(\n        C.accounts\n          .where(\"provider\", \"==\", provider)\n          .where(mapper.toDb(\"providerAccountId\"), \"==\", providerAccountId)\n      )\n      if (!account) return null\n\n      return await getDoc(C.users.doc(account.userId))\n    },\n\n    async updateUser(partialUser) {\n      if (!partialUser.id) throw new Error(\"[updateUser] Missing id\")\n\n      const userRef = C.users.doc(partialUser.id)\n\n      await userRef.set(partialUser, { merge: true })\n\n      const user = await getDoc(userRef)\n      if (!user) throw new Error(\"[updateUser] Failed to fetch updated user\")\n\n      return user\n    },\n\n    async deleteUser(userId) {\n      await db.runTransaction(async (transaction) => {\n        const accounts = await C.accounts\n          .where(mapper.toDb(\"userId\"), \"==\", userId)\n          .get()\n        const sessions = await C.sessions\n          .where(mapper.toDb(\"userId\"), \"==\", userId)\n          .get()\n\n        transaction.delete(C.users.doc(userId))\n\n        accounts.forEach((account) => transaction.delete(account.ref))\n        sessions.forEach((session) => transaction.delete(session.ref))\n      })","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/adapter-firebase/src/index.ts#L118-L154","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Audit Firestore triggers/extensions on the users collection that might delete or restrict the doc right after writes.","Fix the custom getDoc helper to honor snapshot existence and return mapped data correctly.","Verify security rules permit read access for the adapter's credentials on the users collection.","Serialize user-deletion and user-update flows to avoid the delete/update race."],"exampleFix":"// before\nawait userRef.set(partialUser, { merge: true })\nconst user = await getDoc(userRef)\nif (!user) throw new Error('[updateUser] Failed to fetch updated user')\n// after\nawait userRef.set(partialUser, { merge: true })\nconst snap = await userRef.get()\nif (!snap.exists) throw new Error('[updateUser] Failed to fetch updated user')\nconst user = mapper.fromDb({ id: snap.id, ...snap.data() })","handlingStrategy":"try-catch","validationCode":"const before = await userRef.get()\nif (!before.exists) throw new Error(`User doc ${partialUser.id} missing before update`)","typeGuard":"function isPopulatedDoc<T>(d: T | undefined | null): d is T {\n  return d !== undefined && d !== null\n}","tryCatchPattern":"try {\n  await adapter.updateUser({ id, ...patch })\n} catch (e) {\n  if ((e as Error).message.includes('Failed to fetch updated user')) {\n    console.warn(`Update on ${id} succeeded but readback failed; check triggers/rules`)\n    return\n  }\n  throw e\n}","preventionTips":["Audit onWrite/onDelete Cloud Functions and extensions on the users collection.","Avoid running deleteUser and updateUser concurrently for the same user.","Have the getDoc helper honor snapshot.exists and return mapped data."],"tags":["firebase","firestore","database","not-found","race-condition"],"backgroundTag":"record-not-found","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}