The FAILED_PRECONDITION error occurs when a Firestore operation fails because necessary preconditions (like composite indexes or transaction constraints) are not met. Most commonly caused by missing indexes on compound queries combining where() and orderBy().
Firebase Firestore returns this error when an operation is rejected because the system is not in the required state to complete it. This is Firestore's way of enforcing data consistency and preventing invalid operations. The error can occur in several contexts: (1) Composite indexes are missing for queries that combine multiple filters or sorting, (2) A transaction is attempting to modify a document that has changed since the transaction began (optimistic concurrency control), (3) A document is currently locked by another concurrent write operation, or (4) Security rules or emulator configuration is preventing the operation.
When Firestore encounters a query that needs an index, it usually logs a direct link in the console:
You can create a composite index by going to:
https://console.firebase.google.com/v1/...If you see this link, click it to auto-create the required index. On Android (React Native), check adb logcat output for the index link instead of the browser console.
If no link appears, proceed to the next step.
If the automatic link did not appear:
1. Go to [Firebase Console](https://console.firebase.google.com)
2. Select your project and navigate to Firestore Database
3. Click on the Indexes tab (next to Collections)
4. Click Create Index
5. Select your collection name
6. Add the fields you're querying on:
- For .where("status", "==", "active").orderBy("createdAt", "desc"), add:
- Field: status (Ascending)
- Field: createdAt (Descending)
7. Click Create Index
The index will take 1-5 minutes to build. Your queries will work once the index status shows "Enabled".
If you're seeing FAILED_PRECONDITION on transactions, implement retry logic:
import { getFirestore, runTransaction, doc } from "firebase/firestore";
const db = getFirestore();
const maxRetries = 3;
let retries = 0;
async function updateWithRetry() {
while (retries < maxRetries) {
try {
await runTransaction(db, async (transaction) => {
const userRef = doc(db, "users", "user123");
const userDoc = await transaction.get(userRef);
if (!userDoc.exists()) throw new Error("Document not found");
transaction.update(userRef, {
score: userDoc.data().score + 10,
});
});
console.log("Transaction succeeded");
break;
} catch (error: any) {
if (error.code === "failed-precondition" && retries < maxRetries - 1) {
const delay = Math.pow(2, retries) * 100; // 100ms, 200ms, 400ms
await new Promise((resolve) => setTimeout(resolve, delay));
retries++;
} else {
throw error;
}
}
}
}This exponential backoff gives competing transactions time to complete before retrying.
FAILED_PRECONDITION can sometimes be a masked security rule denial. Check your rules:
1. Go to Firebase Console > Firestore > Rules tab
2. Ensure your rules allow the operation. Example:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
// Allow authenticated users to read/write their own documents
allow read, write: if request.auth.uid == userId;
}
match /posts/{postId} {
// Allow reads, require authentication for writes
allow read: if true;
allow write: if request.auth != null;
}
}
}3. Click Publish to apply rule changes
4. Retry your operation
If you're encountering FAILED_PRECONDITION in Cloud Functions:
1. Start the Firebase Emulator Suite:
firebase emulators:start2. Update your code to use the emulator:
import { connectFirestoreEmulator, getFirestore } from "firebase/firestore";
if (process.env.NODE_ENV === "development") {
connectFirestoreEmulator(getFirestore(), "localhost", 8080);
}3. Run your test against the emulator to see clearer error messages
4. Once tests pass locally, deploy to production:
firebase deploy --only functions,firestoreCollection group queries require explicit indexes:
1. Use collectionGroup() in your code:
const q = query(
collectionGroup(db, "comments"),
where("authorId", "==", userId),
orderBy("createdAt", "desc")
);2. Firestore will log an index creation link. Click it, or manually create it in:
- Firebase Console > Firestore > Indexes > Create Index
- Collection: Leave blank for collection group
- Fields: authorId (Ascending), createdAt (Descending)
3. Wait for the index to build (1-5 minutes), then retry the query.
FAILED_PRECONDITION is Firestore's primary mechanism for enforcing consistency. Unlike some databases that silently ignore constraints, Firestore explicitly fails the operation rather than allowing corrupted state.
Transaction Internals: Firestore uses optimistic concurrency control. When you call runTransaction(), it reads documents at a snapshot in time, executes your transaction function, then tries to commit. If any read document changed between the read and commit, Firestore rejects the entire transaction with FAILED_PRECONDITION to prevent data inconsistency. Retrying with backoff is the correct pattern here.
Composite Index Performance: A missing index doesn't mean your query is impossibleโFirestore could do a full collection scan, but that's expensive and slow. By requiring an index, Firestore guarantees O(log n) query performance and prevents runaway costs from accidental full scans.
Emulator Quirks: The Firebase Emulator Suite may have stale state from previous test runs. If you continue seeing FAILED_PRECONDITION after creating indexes, try restarting the emulator with firebase emulators:start --clear.
messaging/UNSPECIFIED_ERROR: No additional information available
How to fix "messaging/UNSPECIFIED_ERROR: No additional information available" in Firebase Cloud Messaging
App Check: reCAPTCHA Score Too Low
App Check reCAPTCHA Score Too Low
storage/invalid-url: Invalid URL format for Cloud Storage reference
How to fix invalid URL format in Firebase Cloud Storage
auth/missing-uid: User ID identifier required
How to fix "auth/missing-uid: User ID identifier required" in Firebase
auth/invalid-argument: Invalid parameter passed to method
How to fix "auth/invalid-argument: Invalid parameter passed to method" in Firebase