Profiles·Public

firebase

semver>=9.0.0postconditions35functions35last verified2026-06-24coverage score83%

Postconditions: what we check

  • signInWithEmailAndPassword · auth-error
    error
    WhenAny Firebase auth failure: invalid email (auth/invalid-email), wrong password (auth/wrong-password), user not found (auth/user-not-found), user disabled (auth/user-disabled), network failure (auth/network-request-failed), or too many requests (auth/too-many-requests).
    ThrowsFirebaseError with code property. Common codes: auth/invalid-email, auth/wrong-password, auth/user-not-found, auth/user-disabled, auth/network-request-failed, auth/too-many-requests. FirebaseError extends Error with code: string and customData: object.
    Required handlingCaller MUST wrap await signInWithEmailAndPassword() in try-catch. Auth failures are common in production — invalid credentials, disabled accounts. Unhandled rejection crashes the process or returns 500 to the user. try { const credential = await signInWithEmailAndPassword(auth, email, password); return credential.user; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/wrong-password') throw new Error('Invalid password'); if (error.code === 'auth/user-not-found') throw new Error('User not found'); } throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[1][2]
  • createUserWithEmailAndPassword · auth-error
    error
    WhenAny Firebase auth failure: email already in use (auth/email-already-in-use), invalid email (auth/invalid-email), weak password (auth/weak-password), operation not allowed (auth/operation-not-allowed), or network failure.
    ThrowsFirebaseError with code. Common codes: auth/email-already-in-use, auth/invalid-email, auth/weak-password, auth/operation-not-allowed, auth/network-request-failed.
    Required handlingCaller MUST wrap await createUserWithEmailAndPassword() in try-catch. Registration failures are expected (email conflicts, weak passwords). try { const credential = await createUserWithEmailAndPassword(auth, email, password); return credential.user; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/email-already-in-use') throw new Error('Email taken'); if (error.code === 'auth/weak-password') throw new Error('Password too weak'); } throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[3][2]
  • signInWithPopup · auth-error
    error
    WhenAny auth failure: popup blocked (auth/popup-blocked), user cancelled (auth/popup-closed-by-user), account exists with different credential (auth/account-exists-with-different-credential), network failure, or cancelled popup before completion (auth/cancelled-popup-request).
    ThrowsFirebaseError with code. Common codes: auth/popup-blocked, auth/popup-closed-by-user, auth/account-exists-with-different-credential, auth/cancelled-popup-request, auth/network-request-failed.
    Required handlingCaller MUST wrap await signInWithPopup() in try-catch. Popup blocking is common — adblockers and browser settings frequently block popups. User cancellation is also a normal flow. try { const result = await signInWithPopup(auth, provider); return result.user; } catch (error) { if (error instanceof FirebaseError && error.code === 'auth/popup-blocked') { // Fallback to redirect or inform user } throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[4][5]
  • getDocs · firestore-error
    error
    WhenAny Firestore failure: permission denied (permission-denied), network failure (unavailable), resource not found (not-found), invalid query arguments (invalid-argument), or unauthenticated (unauthenticated).
    ThrowsFirebaseError with code. Common codes: permission-denied, unavailable, not-found, invalid-argument, unauthenticated, resource-exhausted (quota).
    Required handlingCaller MUST wrap await getDocs() in try-catch. Permission denied errors happen when Firestore Security Rules block access. Network failures occur in offline scenarios or during Firebase outages. try { const snapshot = await getDocs(q); return snapshot.docs.map(doc => doc.data()); } catch (error) { console.error('Firestore query failed:', error.message); throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[6][7]
  • addDoc · firestore-error
    error
    WhenAny Firestore failure: permission denied, invalid data (undefined values, circular references), network failure, or quota exceeded.
    ThrowsFirebaseError with code. Common codes: permission-denied, invalid-argument, unavailable, unauthenticated, resource-exhausted.
    Required handlingCaller MUST wrap await addDoc() in try-catch. Permission denied is common when users are not authenticated or Firestore Security Rules block writes. try { const docRef = await addDoc(collection(db, 'items'), data); return docRef.id; } catch (error) { console.error('Failed to add document:', error.message); throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[8][9]
  • setDoc · firestore-error
    error
    WhenAny Firestore failure: permission denied, invalid data, network failure, or quota exceeded.
    ThrowsFirebaseError with code. Common codes: permission-denied, invalid-argument, unavailable, unauthenticated, resource-exhausted.
    Required handlingCaller MUST wrap await setDoc() in try-catch. try { await setDoc(doc(db, 'users', userId), userData); } catch (error) { console.error('Failed to set document:', error.message); throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[10][9]
  • updateDoc · firestore-error
    error
    WhenAny Firestore failure: document not found (not-found), permission denied, invalid data, network failure, or unauthenticated.
    ThrowsFirebaseError with code. Common codes: not-found, permission-denied, invalid-argument, unavailable, unauthenticated.
    Required handlingCaller MUST wrap await updateDoc() in try-catch. updateDoc() throws not-found if the document doesn't exist (unlike setDoc). try { await updateDoc(docRef, { lastUpdated: new Date() }); } catch (error) { console.error('Failed to update document:', error.message); throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[11][9]
  • deleteDoc · firestore-error
    error
    WhenAny Firestore failure: permission denied, network failure, or unauthenticated. (Does NOT throw if document doesn't exist.)
    ThrowsFirebaseError with code. Common codes: permission-denied, unavailable, unauthenticated, resource-exhausted.
    Required handlingCaller MUST wrap await deleteDoc() in try-catch. try { await deleteDoc(doc(db, 'items', itemId)); } catch (error) { console.error('Failed to delete document:', error.message); throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[12][13]
  • sendPasswordResetEmail · auth-send-password-reset-invalid-email
    error
    WhensendPasswordResetEmail() called without try-catch when email is invalid format or the Auth instance is misconfigured.
    ThrowsFirebaseError with code: auth/invalid-email (malformed email address), auth/missing-email (empty email), auth/invalid-api-key (bad Firebase config), auth/network-request-failed (network failure), auth/too-many-requests (rate limit exceeded). Note: auth/user-not-found is NOT thrown when Email Enumeration Protection is enabled (the default since 2023) — Firebase returns success silently for unknown emails.
    Required handlingCaller MUST wrap await sendPasswordResetEmail() in try-catch. auth/invalid-email means client-side validation should run first. auth/too-many-requests means implement rate limiting in the UI. NEVER tell users whether the email exists — return generic "if account exists, email was sent". try { await sendPasswordResetEmail(auth, email); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/invalid-email') throw new Error('Invalid email format'); if (error.code === 'auth/too-many-requests') throw new Error('Too many attempts'); } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilitysilent
    Sources[14][15]
  • sendEmailVerification · auth-send-email-verification-error
    error
    WhensendEmailVerification() called without try-catch.
    ThrowsFirebaseError with code: auth/too-many-requests (sending too fast), auth/user-token-expired (user session expired — requires re-authentication), auth/network-request-failed (network failure), auth/user-disabled (account suspended), auth/invalid-user-token (user token invalid — session may be stale).
    Required handlingCaller MUST wrap await sendEmailVerification() in try-catch. auth/too-many-requests: Firebase limits verification email frequency — handle gracefully and inform user to wait before resending. auth/user-token-expired: User must sign in again before verification can be sent. try { await sendEmailVerification(user); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/too-many-requests') { throw new Error('Verification email already sent. Please wait before resending.'); } } throw error; }
    costlowin prodimmediate exceptionusers seeauthentication failurevisibilitysilent
    Sources[16][17]
  • deleteUser · auth-delete-user-requires-recent-login
    error
    WhendeleteUser() called without try-catch when user has not recently authenticated.
    ThrowsFirebaseError with code: auth/requires-recent-login (user's last sign-in was too long ago — must re-authenticate before this security-sensitive operation), auth/user-not-found (user was already deleted — race condition), auth/network-request-failed (network failure), auth/user-disabled (account was suspended).
    Required handlingCaller MUST wrap await deleteUser() in try-catch. auth/requires-recent-login is THE most important case: prompt user to sign in again using reauthenticateWithCredential() before retrying. This is the standard Firebase security pattern for sensitive operations. try { await deleteUser(user); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/requires-recent-login') { // Prompt re-authentication flow, then retry await reauthenticateWithCredential(user, credential); await deleteUser(user); } } throw error; }
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[18][19]
  • signOut · auth-sign-out-error
    warning
    WhensignOut() called without try-catch.
    ThrowsFirebaseError with code: auth/network-request-failed (network failure during token revocation), auth/internal-error (internal Firebase error, rare). Note: signOut() clears local auth state even if the server request fails, so users are effectively signed out locally even on error.
    Required handlingCaller MUST wrap await signOut() in try-catch to prevent unhandled rejections. Network failures during signOut are rare but possible. The local session is cleared regardless, so handle gracefully (log the error, redirect to login page). try { await signOut(auth); router.push('/login'); } catch (error) { // Sign out failed on server, but local session is cleared console.error('Sign out error:', error); router.push('/login'); // Redirect regardless }
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[20]
  • getIdToken · auth-get-id-token-expired
    error
    WhengetIdToken() called without try-catch when user session is expired or revoked.
    ThrowsFirebaseError with code: auth/user-token-expired (token expired and cannot be refreshed — user must sign in again), auth/user-disabled (account suspended while token was valid), auth/user-not-found (user deleted), auth/network-request-failed (network failure during token refresh), auth/invalid-user-token (token is malformed).
    Required handlingCaller MUST wrap await getIdToken() in try-catch. auth/user-token-expired is the most common case — user session invalidated (password changed, token revoked from console, user deleted). On token errors, sign the user out and redirect to login. try { const token = await getIdToken(user); // Use token in Authorization header return fetch('/api/...', { headers: { Authorization: `Bearer ${token}` } }); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/user-token-expired' || error.code === 'auth/user-not-found') { await signOut(auth); router.push('/login'); } } throw error; }
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[21]
  • updateEmail · auth-update-email-requires-recent-login
    error
    WhenupdateEmail() called without try-catch when user session is stale.
    ThrowsFirebaseError with code: auth/requires-recent-login (must re-authenticate before changing email — security requirement), auth/email-already-in-use (email taken by another account), auth/invalid-email (malformed email), auth/operation-not-allowed (Email Enumeration Protection enabled — use verifyBeforeUpdateEmail instead), auth/network-request-failed (network failure).
    Required handlingCaller MUST wrap await updateEmail() in try-catch. auth/requires-recent-login is the most common error — prompt re-authentication. IMPORTANT: auth/operation-not-allowed means Email Enumeration Protection is enabled (default since 2023) — migrate to verifyBeforeUpdateEmail() which is the secure alternative. try { await updateEmail(user, newEmail); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/requires-recent-login') { throw new Error('Please sign in again to change your email'); } if (error.code === 'auth/email-already-in-use') { throw new Error('Email already in use'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[22][23]
  • updatePassword · auth-update-password-error
    error
    WhenupdatePassword() called without try-catch.
    ThrowsFirebaseError with code: auth/requires-recent-login (must re-authenticate — changing passwords is a security-sensitive operation), auth/weak-password (password too short, usually < 6 characters), auth/network-request-failed (network failure), auth/user-disabled (account suspended).
    Required handlingCaller MUST wrap await updatePassword() in try-catch. auth/requires-recent-login requires prompting the user to sign in again. auth/weak-password should be caught with client-side validation first. try { await updatePassword(user, newPassword); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/requires-recent-login') { throw new Error('Please sign in again to change your password'); } if (error.code === 'auth/weak-password') { throw new Error('Password must be at least 6 characters'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[24][25]
  • confirmPasswordReset · auth-confirm-password-reset-error
    error
    WhenconfirmPasswordReset() called without try-catch when the reset code is invalid or expired.
    ThrowsFirebaseError with code: auth/expired-action-code (reset link older than 1 hour — user must request a new one), auth/invalid-action-code (malformed or already-used code), auth/user-not-found (account deleted since reset was requested), auth/user-disabled (account suspended), auth/weak-password (new password too short), auth/network-request-failed (network failure).
    Required handlingCaller MUST wrap await confirmPasswordReset() in try-catch. auth/expired-action-code is the most common error — reset links expire after 1 hour. Prompt the user to request a new reset email. auth/invalid-action-code may mean the link was already used (single-use codes). try { await confirmPasswordReset(auth, oobCode, newPassword); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/expired-action-code') { throw new Error('Reset link has expired. Please request a new one.'); } if (error.code === 'auth/invalid-action-code') { throw new Error('Reset link is invalid or has already been used.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[26]
  • getDoc · firestore-get-doc-error
    error
    WhengetDoc() called without try-catch.
    ThrowsFirebaseError (FirestoreError) with code: permission-denied (Firestore Security Rules block access), unavailable (network failure or Firebase outage — may resolve after retry), unauthenticated (user not signed in when rules require auth), not-found (collection or database doesn't exist — not thrown for missing docs). IMPORTANT: Returns empty DocumentSnapshot (snapshot.exists() === false) for missing documents — does NOT throw. Check snapshot.exists() before accessing snapshot.data().
    Required handlingCaller MUST wrap await getDoc() in try-catch AND check snapshot.exists() before access. permission-denied is very common during development (Firestore rules misconfigured). Failing to check exists() causes data() to return undefined, causing null reference errors. try { const snapshot = await getDoc(doc(db, 'users', userId)); if (!snapshot.exists()) { throw new Error('User not found'); } return snapshot.data(); } catch (error) { if (error instanceof FirebaseError) { console.error('Firestore read failed:', error.code, error.message); } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[27][7]
  • runTransaction · firestore-transaction-contention
    error
    WhenrunTransaction() called without try-catch when there is high write contention or the transaction function throws.
    ThrowsFirebaseError (FirestoreError) with code: aborted (failed to commit after 5 retries due to high write contention), permission-denied (Security Rules block a read or write inside the transaction), unavailable (network failure), failed-precondition (transaction read document that no longer exists), resource-exhausted (quota exceeded), invalid-argument (more than 500 writes in one transaction). Also re-throws any error thrown inside the updateFunction.
    Required handlingCaller MUST wrap await runTransaction() in try-catch. aborted after 5 retries is the most critical case — indicates hot document (high contention). Consider sharding the counter or using FieldValue.increment() instead of transactions for counters. Errors thrown inside updateFunction propagate as-is — wrap with custom errors for clarity. try { const result = await runTransaction(db, async (t) => { const docSnap = await t.get(docRef); if (!docSnap.exists()) throw new Error('Document not found'); t.update(docRef, { count: docSnap.data().count + 1 }); return docSnap.data().count + 1; }); return result; } catch (error) { if (error instanceof FirebaseError && error.code === 'aborted') { throw new Error('Transaction failed after retries — high contention on document'); } throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[28][29]
  • uploadBytes · storage-upload-bytes-error
    error
    WhenuploadBytes() called without try-catch.
    ThrowsStorageError (extends FirebaseError) with code: storage/unauthorized (Security Rules block the upload — user not authenticated or path not allowed), storage/quota-exceeded (Firebase Storage quota for the project exceeded), storage/canceled (upload was cancelled), storage/retry-limit-exceeded (network too slow or unstable, max retries reached), storage/invalid-checksum (data corrupted in transit), storage/unauthenticated (no authenticated user). StorageError.code is prefixed with 'storage/'.
    Required handlingCaller MUST wrap await uploadBytes() in try-catch. storage/unauthorized is the most common error — check Firebase Storage Security Rules. storage/quota-exceeded requires checking Firebase project billing/quota limits. storage/retry-limit-exceeded indicates persistent network issues. try { const result = await uploadBytes(storageRef, file); return result.ref.fullPath; } catch (error) { if (error instanceof StorageError) { if (error.code === 'storage/unauthorized') { throw new Error('Not authorized to upload files'); } if (error.code === 'storage/quota-exceeded') { throw new Error('Storage quota exceeded'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[30][31]
  • getDownloadURL · storage-get-download-url-error
    error
    WhengetDownloadURL() called without try-catch.
    ThrowsStorageError (extends FirebaseError) with code: storage/object-not-found (file was deleted or path is wrong — very common bug when referencing stale paths), storage/unauthorized (Security Rules deny read access), storage/no-download-url (file exists but has no public download URL — requires making the bucket public or using signed URLs), storage/bucket-not-found (wrong bucket name in Firebase config), storage/unauthenticated (rules require auth).
    Required handlingCaller MUST wrap await getDownloadURL() in try-catch. storage/object-not-found is the most common error — file was deleted, moved, or the stored path is wrong (race condition between upload and read is common). Validate file existence before serving download URLs to users. try { const url = await getDownloadURL(ref(storage, filePath)); return url; } catch (error) { if (error instanceof StorageError) { if (error.code === 'storage/object-not-found') { throw new Error('File not found'); } if (error.code === 'storage/unauthorized') { throw new Error('Not authorized to access this file'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[32][33]
  • signInWithEmailLink · email-link-expired-or-invalid
    error
    WhensignInWithEmailLink() called without try-catch. The email link has expired or was already used, or the link doesn't match the email address provided.
    ThrowsFirebaseError with code: auth/expired-action-code (link expired — 10 minute TTL), auth/invalid-action-code (link already used or malformed), auth/invalid-email (email doesn't match the one the link was sent to), auth/user-disabled (account disabled after link was sent), auth/network-request-failed (network failure).
    Required handlingCaller MUST wrap await signInWithEmailLink() in try-catch. Expired and already-used links are the most common production failures — users often click links multiple times or wait too long. Each link is single-use and has a 10-minute expiration. try { const result = await signInWithEmailLink(auth, email, window.location.href); window.localStorage.removeItem('emailForSignIn'); return result.user; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/expired-action-code') { throw new Error('Sign-in link has expired. Please request a new one.'); } if (error.code === 'auth/invalid-action-code') { throw new Error('Sign-in link already used. Please request a new one.'); } if (error.code === 'auth/invalid-email') { throw new Error('Email does not match the sign-in link.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[34][35]
  • signInAnonymously · anonymous-auth-not-enabled-or-quota-exceeded
    error
    WhensignInAnonymously() called without try-catch. Anonymous auth not enabled in Firebase Console, or quota for anonymous accounts exceeded.
    ThrowsFirebaseError with code: auth/operation-not-allowed (anonymous authentication not enabled in Firebase Console — frequent misconfiguration in new projects), auth/quota-exceeded (new anonymous sign-ups rate-limited, common when deployed to production without proper settings), auth/network-request-failed (network failure).
    Required handlingCaller MUST wrap await signInAnonymously() in try-catch. auth/operation-not-allowed means Anonymous sign-in is disabled in Firebase Console — developers often forget to enable it for new environments (staging, production). auth/quota-exceeded means Firebase is rate-limiting new anonymous sign-ups. try { const result = await signInAnonymously(auth); return result.user; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/operation-not-allowed') { throw new Error('Anonymous sign-in is disabled. Enable it in Firebase Console.'); } if (error.code === 'auth/quota-exceeded') { throw new Error('Too many anonymous sign-in attempts. Please try again later.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[36][37]
  • updateProfile · update-profile-error
    warning
    WhenupdateProfile() called without try-catch. User's token expired, user was deleted, or network failure.
    ThrowsFirebaseError with code: auth/network-request-failed (network failure during profile update — common in flaky connections), auth/user-token-expired (user's auth token has expired, requires re-authentication), auth/user-not-found (user account was deleted between sign-in and the profile update call).
    Required handlingCaller MUST wrap await updateProfile() in try-catch. auth/user-token-expired requires the user to sign in again. This function is commonly called immediately after createUserWithEmailAndPassword() in onboarding flows — both should be wrapped together. try { await updateProfile(auth.currentUser, { displayName: name, photoURL: avatarUrl }); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/network-request-failed') { throw new Error('Network error updating profile. Please try again.'); } if (error.code === 'auth/user-token-expired') { throw new Error('Session expired. Please sign in again.'); } } throw error; }
    costlowin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[38][39]
  • linkWithCredential · link-credential-conflict
    error
    WhenlinkWithCredential() called without try-catch. The credential is already associated with another Firebase account, or an account with that email already exists.
    ThrowsFirebaseError with code: auth/credential-already-in-use (the credential is already linked to a different Firebase user account — cannot link the same Google/GitHub account to multiple Firebase users), auth/account-exists-with-different-credential (an account with the same email already exists but uses a different sign-in method — e.g. user has email/password account and tries to link Google with same email), auth/email-already-in-use (for email/password credential linking when email is taken), auth/provider-already-linked (user already has this provider linked), auth/requires-recent-login (security-sensitive operation requires recent sign-in).
    Required handlingCaller MUST wrap await linkWithCredential() in try-catch. auth/credential-already-in-use is the most important case — the linked credential's user needs to be merged or the conflict resolved. auth/account-exists-with-different-credential is very common in social auth flows where users try to link an OAuth account that matches an existing email/password account. try { const result = await linkWithCredential(user, credential); return result.user; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/credential-already-in-use') { throw new Error('This account is already linked to another user.'); } if (error.code === 'auth/account-exists-with-different-credential') { throw new Error('An account with this email already exists with a different sign-in method.'); } if (error.code === 'auth/requires-recent-login') { throw new Error('Please sign in again before linking accounts.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[40][41]
  • reauthenticateWithCredential · reauth-credential-error
    error
    WhenreauthenticateWithCredential() called without try-catch. Wrong password, stale credential, or user mismatch.
    ThrowsFirebaseError with code: auth/wrong-password (incorrect password for email/password credential — user mistyped current password), auth/user-mismatch (credential does not correspond to the currently signed-in user — wrong account), auth/invalid-credential (the auth credential is malformed or has expired — OAuth token expired), auth/user-not-found (user account was deleted), auth/network-request-failed (network failure during re-auth).
    Required handlingCaller MUST wrap await reauthenticateWithCredential() in try-catch. This is required before deleteUser() or updateEmail() — if it fails, the subsequent sensitive operation must not proceed. auth/wrong-password is the most common failure. auth/user-mismatch means the credentials don't belong to the current user. const credential = EmailAuthProvider.credential(email, currentPassword); try { await reauthenticateWithCredential(auth.currentUser, credential); // Now safe to call deleteUser() or updateEmail() } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/wrong-password') { throw new Error('Current password is incorrect.'); } if (error.code === 'auth/user-mismatch') { throw new Error('Credential does not match the current user.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[42][43]
  • verifyBeforeUpdateEmail · verify-before-update-email-error
    error
    WhenverifyBeforeUpdateEmail() called without try-catch. Email already in use, requires recent login, or network failure.
    ThrowsFirebaseError with code: auth/email-already-in-use (new email already registered to another account), auth/requires-recent-login (security-sensitive operation — user must have signed in within the last few minutes), auth/invalid-email (new email address is malformed), auth/network-request-failed (network failure during verification email send), auth/operation-not-allowed (email/password accounts not enabled — unlikely but possible in Identity Platform configs).
    Required handlingCaller MUST wrap await verifyBeforeUpdateEmail() in try-catch. auth/requires-recent-login is the most common failure — the user must reauthenticate before changing their email. auth/email-already-in-use means the new email is taken. try { await verifyBeforeUpdateEmail(auth.currentUser, newEmail); // Tell user to check their new email inbox } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/email-already-in-use') { throw new Error('This email address is already registered.'); } if (error.code === 'auth/requires-recent-login') { throw new Error('Please sign in again before changing your email.'); } } throw error; }
    costlowin prodimmediate exceptionusers seeauthentication failurevisibilitysilent
    Sources[44][45]
  • writeBatch.commit · batch-commit-permission-denied
    error
    Whenbatch.commit() called without try-catch. Firestore Security Rules deny one or more writes in the batch, or the batch exceeds 500 operations.
    ThrowsFirebaseError (FirestoreError) with code: permission-denied (Security Rules block one or more write operations in the batch — the entire batch fails atomically), not-found (a batch.update() or batch.delete() references a document that does not exist), resource-exhausted (batch exceeds 500 operations or rate limits), unavailable (Firestore temporarily unavailable — transient network/service issue), unauthenticated (user not authenticated and rules require auth). The WriteBatch.commit() Promise will never resolve while offline.
    Required handlingCaller MUST wrap await batch.commit() in try-catch. A single permission-denied write in the batch fails ALL writes atomically. Check that all document paths in the batch pass Security Rules before committing. Monitor for resource-exhausted if batches dynamically grow with user-generated content. const batch = writeBatch(db); batch.set(doc(db, 'users', userId), userData); batch.update(doc(db, 'counters', 'users'), { count: increment(1) }); try { await batch.commit(); } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'permission-denied') { throw new Error('Not authorized to perform this update.'); } if (error.code === 'resource-exhausted') { throw new Error('Batch too large or rate limit exceeded. Reduce batch size.'); } } throw error; }
    costhighin prodimmediate exceptionusers seelost datavisibilitysilent
    Sources[46][47]
  • getCountFromServer · count-from-server-error
    warning
    WhengetCountFromServer() called without try-catch. Firestore Security Rules deny the query, or the underlying index is not ready.
    ThrowsFirebaseError (FirestoreError) with code: permission-denied (Security Rules deny the underlying query the count is based on — common when the query has compound filters that require field-level auth), unauthenticated (user not authenticated and Security Rules require auth), failed-precondition (composite index not yet built for the query — very common during development when adding new queries), resource-exhausted (project quota exceeded or too many reads in short window), unavailable (Firestore temporarily unavailable).
    Required handlingCaller MUST wrap await getCountFromServer() in try-catch. failed-precondition with a message about missing indexes is very common during development — Firestore will include the index creation URL in the error message. permission-denied occurs when Security Rules don't allow the underlying collection read. try { const snapshot = await getCountFromServer(query(collection(db, 'orders'), where('userId', '==', userId))); return snapshot.data().count; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'permission-denied') { throw new Error('Not authorized to count this collection.'); } if (error.code === 'failed-precondition') { throw new Error('Missing Firestore index. Check Firebase Console.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[48][49]
  • deleteObject · delete-object-error
    error
    WhendeleteObject() called without try-catch. File does not exist, or Security Rules deny the delete operation.
    ThrowsStorageError (extends FirebaseError) with code: storage/object-not-found (file was already deleted or path is wrong — concurrent deletion is common in user-facing apps where users can delete from multiple sessions), storage/unauthorized (Security Rules deny the delete — user does not own the file or rules require ownership check), storage/unauthenticated (user is not authenticated but rules require auth), storage/retry-limit-exceeded (network failure with all retries exhausted).
    Required handlingCaller MUST wrap await deleteObject() in try-catch. storage/object-not-found should be treated as a success (idempotent delete is safe) or at minimum should not crash the user-facing operation. Always check Security Rules: rules must verify file ownership to prevent users deleting others' files. try { await deleteObject(ref(storage, filePath)); } catch (error) { if (error instanceof StorageError) { if (error.code === 'storage/object-not-found') { // File already deleted — treat as success for idempotent delete return; } if (error.code === 'storage/unauthorized') { throw new Error('Not authorized to delete this file.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[50][51]
  • httpsCallable · functions-call-unauthenticated-or-permission-denied
    error
    WhenhttpsCallable(functions, name) result called without try-catch. User not authenticated, permission denied, function not found, or internal server error.
    ThrowsFunctionsError (extends FirebaseError) with code: functions/unauthenticated (function requires Firebase Authentication and user is not signed in), functions/permission-denied (user is signed in but does not have permission to call this function — typically enforced via Firebase Auth claims check in the function), functions/not-found (function does not exist or was not deployed — common during development), functions/internal (unhandled exception in the Cloud Function — function threw an error not wrapped in HttpsError), functions/unavailable (Cloud Functions temporarily unavailable — transient), functions/deadline-exceeded (function execution timeout — 60s default), functions/resource-exhausted (quota exceeded — max concurrent calls reached).
    Required handlingCaller MUST wrap await fn(data) in try-catch, NOT await httpsCallable() itself. functions/unauthenticated means the user must sign in before calling the function. functions/internal means the Cloud Function itself crashed — check server logs. functions/permission-denied is an application-level authorization failure. Use error.code to distinguish user-facing errors from internal server errors. const sendInvite = httpsCallable(functions, 'sendInvite'); try { const result = await sendInvite({ email, organizationId }); return result.data; } catch (error) { if (error instanceof FunctionsError) { if (error.code === 'functions/unauthenticated') { throw new Error('Please sign in to perform this action.'); } if (error.code === 'functions/permission-denied') { throw new Error('You do not have permission to perform this action.'); } if (error.code === 'functions/internal') { throw new Error('Server error. Please try again later.'); } } throw error; }
    costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[52][53]
  • applyActionCode · apply-action-code-error
    error
    WhenapplyActionCode(auth, oobCode) called without try-catch. Action code is expired, invalid (malformed or already used), or the associated user has been disabled or deleted.
    ThrowsFirebaseError with code property. Common codes: auth/expired-action-code (code has passed its TTL — Firebase action codes expire after ~1 hour by default), auth/invalid-action-code (code is malformed, used a second time, or revoked), auth/user-disabled (the user account associated with the code was disabled by an admin), auth/user-not-found (the user account associated with the code was deleted between email send and link click).
    Required handlingCaller MUST wrap await applyActionCode() in try-catch. Action codes commonly fail in production — users click email links hours later, paste codes into the wrong tab, or retry already-applied codes. Unhandled rejection breaks the verification flow and leaves the user staring at a generic error page. try { await applyActionCode(auth, oobCode); return { verified: true }; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/expired-action-code') { return { error: 'This verification link has expired. Please request a new one.' }; } if (error.code === 'auth/invalid-action-code') { return { error: 'This verification link is no longer valid. It may have already been used.' }; } } throw error; }
    costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[54][15]
  • getRedirectResult · redirect-result-error
    error
    WhengetRedirectResult(auth) called without try-catch on the post-redirect page. OAuth provider rejected the sign-in, an account already exists with the same email under a different provider, or the credential is already linked to another user.
    ThrowsFirebaseError with code property. Common codes: auth/account-exists-with-different-credential (the email returned by the provider is already linked to another sign-in method — common when a user signs up with Google then tries to sign in with Apple using the same email), auth/credential-already-in-use (linkWithRedirect: this provider credential is already linked to a different Firebase user — must merge or unlink first), auth/web-storage-unsupported (browser blocks sessionStorage — third-party cookies disabled, Safari ITP, incognito mode), auth/operation-not-supported-in-this-environment (called from a non-browser environment), auth/network-request-failed (network error during token exchange), auth/internal-error (Firebase Auth backend issue).
    Required handlingCaller MUST wrap await getRedirectResult() in try-catch. This is the FIRST thing that runs after a successful OAuth redirect — an unhandled rejection here means the user lands on a broken page with no recovery path. Web storage errors are especially common in Safari and incognito sessions. try { const result = await getRedirectResult(auth); if (result) { return { user: result.user }; } return { user: null }; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/account-exists-with-different-credential') { return { error: 'An account with this email exists. Sign in with your original provider.' }; } if (error.code === 'auth/web-storage-unsupported') { return { error: 'Your browser blocks the storage needed to sign in. Try a different browser or enable third-party cookies.' }; } } throw error; }
    costhighin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[55][56]
  • signInWithCustomToken · custom-token-error
    error
    WhensignInWithCustomToken(auth, token) called without try-catch. Custom token is malformed, expired, signed by a different Firebase project (wrong audience), or the user account was disabled.
    ThrowsFirebaseError with code property. Common codes: auth/invalid-custom-token (token is not a valid Firebase custom token — usually missing claims, wrong format, or expired), auth/custom-token-mismatch (token was signed for a different Firebase project — common when staging tokens leak into production or vice versa), auth/user-disabled (the target uid is disabled in the Firebase console), auth/network-request-failed (network issue during token verification).
    Required handlingCaller MUST wrap await signInWithCustomToken() in try-catch. Custom token sign-in is the bridge between a backend auth system and Firebase — failures here lock users out of every Firebase feature (Firestore, Storage, Functions). Token-mismatch errors are especially insidious because they only surface in production when env vars get swapped. try { const credential = await signInWithCustomToken(auth, customToken); return { user: credential.user }; } catch (error) { if (error instanceof FirebaseError) { if (error.code === 'auth/invalid-custom-token' || error.code === 'auth/custom-token-mismatch') { console.error('Custom token rejected — check backend token minting:', error.code); throw new Error('Authentication failed. Please contact support.'); } } throw error; }
    costhighin prodimmediate exceptionusers seeauthentication failurevisibilityvisible
    Sources[57][58]
  • uploadString · upload-string-error
    error
    WhenuploadString(ref, value, format) called without try-catch. Storage security rules deny the upload, the bucket quota is exhausted, the network drops mid-upload, or the string format is invalid for the declared format type.
    ThrowsStorageError (extends FirebaseError) with code property. Common codes: storage/unauthorized (security rules deny write — common when uid in path doesn't match auth.uid), storage/quota-exceeded (bucket free-tier quota exhausted), storage/retry-limit-exceeded (network failed all retries — slow connection or backend issue), storage/unauthorized-app (App Check failure — common during development), storage/invalid-format (string isn't valid for the declared format, e.g. malformed base64 or data URL with wrong MIME).
    Required handlingCaller MUST wrap await uploadString() in try-catch. Upload failures must be distinguished from success — silently treating a rejection as success leaves downstream features (avatar display, document export) referencing nonexistent objects. try { const snapshot = await uploadString(ref, dataUrl, 'data_url'); return { path: snapshot.ref.fullPath }; } catch (error) { if (error instanceof StorageError) { if (error.code === 'storage/unauthorized') { throw new Error('You do not have permission to upload here.'); } if (error.code === 'storage/quota-exceeded') { throw new Error('Storage quota exceeded. Please contact support.'); } } throw error; }
    costmediumin prodimmediate exceptionusers seelost datavisibilityvisible
    Sources[59][60]
  • getMetadata · get-metadata-error
    error
    WhengetMetadata(ref) called without try-catch. Object does not exist at the referenced path, the user lacks read permission per Storage rules, or the network request fails.
    ThrowsStorageError (extends FirebaseError) with code property. Common codes: storage/object-not-found (no object at this path — common when checking for optional artifacts like profile photos before display), storage/unauthorized (Storage rules deny read access — typical when the path encodes a uid different from auth.uid), storage/retry-limit-exceeded (network failure exhausted retries), storage/unauthorized-app (App Check rejected the request).
    Required handlingCaller MUST wrap await getMetadata() in try-catch. storage/object-not-found is the expected path for "does this file exist?" probes — swallowing rejections silently can mask permission errors as missing-file errors and vice versa, leading to mysteriously broken features. try { const metadata = await getMetadata(ref); return metadata; } catch (error) { if (error instanceof StorageError) { if (error.code === 'storage/object-not-found') { return null; } if (error.code === 'storage/unauthorized') { throw new Error('You do not have permission to view this file.'); } } throw error; }
    costlowin prodimmediate exceptionusers seedegraded performancevisibilityvisible
    Sources[61][62]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
  • [1]
    firebase.google.com/docs/reference/js
    Auth
  • [2]
    firebase.google.com/docs/auth/web
    Password Auth
  • [3]
    firebase.google.com/docs/reference/js
    Auth
  • [4]
    firebase.google.com/docs/reference/js
    Auth
  • [5]
    firebase.google.com/docs/auth/web
    Google Signin
  • [6]
    firebase.google.com/docs/reference/js
    Firestore
  • [7]
    firebase.google.com/docs/firestore/query-data
    Get Data
  • [8]
    firebase.google.com/docs/reference/js
    Firestore
  • [9]
    firebase.google.com/docs/firestore/manage-data
    Add Data
  • [10]
    firebase.google.com/docs/reference/js
    Firestore
  • [11]
    firebase.google.com/docs/reference/js
    Firestore
  • [12]
    firebase.google.com/docs/reference/js
    Firestore
  • [13]
    firebase.google.com/docs/firestore/manage-data
    Delete Data
  • [14]
    firebase.google.com/docs/reference/js
    Auth
  • [15]
    firebase.google.com/docs/auth/web
    Manage Users
  • [16]
    firebase.google.com/docs/reference/js
    Auth
  • [17]
    firebase.google.com/docs/auth/web
    Manage Users
  • [18]
    firebase.google.com/docs/reference/js
    Auth
  • [19]
    firebase.google.com/docs/auth/web
    Manage Users
  • [20]
    firebase.google.com/docs/reference/js
    Auth
  • [21]
    firebase.google.com/docs/reference/js
    Auth
  • [22]
    firebase.google.com/docs/reference/js
    Auth
  • [23]
    firebase.google.com/docs/auth/web
    Manage Users
  • [24]
    firebase.google.com/docs/reference/js
    Auth
  • [25]
    firebase.google.com/docs/auth/web
    Manage Users
  • [26]
    firebase.google.com/docs/reference/js
    Auth
  • [27]
    firebase.google.com/docs/reference/js
    Firestore
  • [28]
    firebase.google.com/docs/reference/js
    Firestore
  • [29]
    firebase.google.com/docs/firestore/manage-data
    Transactions
  • [30]
    firebase.google.com/docs/reference/js
    Storage
  • [31]
    firebase.google.com/docs/storage/web
    Upload Files
  • [32]
    firebase.google.com/docs/reference/js
    Storage
  • [33]
    firebase.google.com/docs/storage/web
    Download Files
  • [34]
    firebase.google.com/docs/auth/web
    Email Link Auth
  • [35]
    firebase.google.com/docs/reference/js
    Auth
  • [36]
    firebase.google.com/docs/auth/web
    Anonymous Auth
  • [37]
    firebase.google.com/docs/reference/js
    Auth
  • [38]
    firebase.google.com/docs/reference/js
    Auth
  • [39]
    firebase.google.com/docs/auth/web
    Manage Users
  • [40]
    firebase.google.com/docs/reference/js
    Auth
  • [41]
    firebase.google.com/docs/auth/web
    Account Linking
  • [42]
    firebase.google.com/docs/reference/js
    Auth
  • [43]
    firebase.google.com/docs/auth/web
    Manage Users
  • [44]
    firebase.google.com/docs/reference/js
    Auth
  • [45]
    firebase.google.com/docs/auth/web
    Manage Users
  • [46]
    firebase.google.com/docs/reference/js
    Firestore .Writebatch
  • [47]
    firebase.google.com/docs/firestore/manage-data
    Transactions
  • [48]
    firebase.google.com/docs/reference/js
    Firestore
  • [49]
    firebase.google.com/docs/firestore/query-data
    Aggregation Queries
  • [50]
    firebase.google.com/docs/reference/js
    Storage
  • [51]
    firebase.google.com/docs/storage/web
    Delete Files
  • [52]
    firebase.google.com/docs/functions/callable
    Callable
  • [53]
    firebase.google.com/docs/reference/js
    Functions
  • [54]
    firebase.google.com/docs/reference/js
    Auth
  • [55]
    firebase.google.com/docs/reference/js
    Auth
  • [56]
    firebase.google.com/docs/auth/web
    Redirect Best Practices
  • [57]
    firebase.google.com/docs/reference/js
    Auth
  • [58]
    firebase.google.com/docs/auth/admin
    Create Custom Tokens
  • [59]
    firebase.google.com/docs/reference/js
    Storage
  • [60]
    firebase.google.com/docs/storage/web
    Handle Errors
  • [61]
    firebase.google.com/docs/reference/js
    Storage
  • [62]
    firebase.google.com/docs/storage/web
    File Metadata

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Firebase — Sources

Behavioral Claims

All functions can throw FirebaseError on network failure, permission denied, invalid credentials, or service errors. This is documented in the official Firebase JavaScript SDK reference.

Official Documentation

Error Handling

Error Codes and Types

Error Type Documentation

Real-World Evidence

Correct Usage (0 violations)

  • namviek (2.4k★) — apps/frontend/libs/firebase.ts: signInWithPopup wrapped in .then().catch() pattern
  • git-friend (44★) — context/auth-context.tsx: signInWithPopup and signOut properly wrapped in try-catch

Known Violation Pattern (manual confirmation)

  • venice (~500★) — connectors/connector-copilot/CopilotClient.ts:35-52: signInWithEmailAndPassword(auth, email, password).then(async (creds) => {...}) — no .catch() on the outer call. This is a TRUE POSITIVE violation.

Package Versions Observed in Production

  • 9.6.3 (hackernews-react-graphql)
  • 9.8.1 (venice)
  • 10.7.1 (namviek)
  • 10.11.0 (Memex)
  • 10.12.1 (penrose)
  • 11.1.0 (upscayl)
  • 11.3.1 (akveo/nebular)
  • 12.7.0 (git-friend)

Notes

  • This contract covers the modular API (v9+) only. The v8 compat API (firebase/compat) uses different method signatures (namespace API like firebase.auth()) and is not covered.
  • Functions are imported from sub-module paths (firebase/auth, firebase/firestore) which the analyzer normalizes to the firebase package.
  • deleteDoc() does NOT throw if the document doesn't exist — it succeeds silently.
  • getAuth(), getFirestore(), collection(), doc(), query(), where() are synchronous helpers and do NOT require try-catch.
Need a different package?
Request a profile