Skip to main content
RapidDev - Software Development Agency
Firebase

How to Fix "Firestore: permission-denied" in Firebase

Error Output
$ Firestore: permission-denied

The 'Firestore: permission-denied' error means your Firestore security rules are blocking the operation your code is attempting. This is the SDK-level error code for the same issue as 'Missing or insufficient permissions.' Use the Firebase Rules Playground to test your rules, ensure queries structurally match rule conditions, and verify user authentication state.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
FirebaseIntermediate10-30 minutesMarch 2026RapidDev Engineering Team
TL;DR

The 'Firestore: permission-denied' error means your Firestore security rules are blocking the operation your code is attempting. This is the SDK-level error code for the same issue as 'Missing or insufficient permissions.' Use the Firebase Rules Playground to test your rules, ensure queries structurally match rule conditions, and verify user authentication state.

What does "Firestore: permission-denied" mean?

When Firestore returns the permission-denied error code, your security rules evaluated the operation and determined it should be blocked. On web this appears as [code=permission-denied], on Android as FirebaseFirestoreException: PERMISSION_DENIED, and on Flutter as [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.

This error is distinct from the more generic 'Missing or insufficient permissions' message in that it specifically comes from the Firestore SDK with a structured error code. The underlying cause is always the same: your security rules deny the operation. However, this version often provides slightly more context about which operation was denied.

The most important concept for understanding this error: Firestore rules are not filters. Firestore evaluates whether a query could theoretically return unauthorized data. If your rules restrict by userId, any query without a matching .where('userId', '==', uid) clause is rejected — even if every document would pass the rule check individually. CollectionGroup queries require special rules matching the subcollection path.

Common causes

The user is not authenticated

and the security rules require request.auth != null for the operation

A read query does not

include a where clause that structurally matches the security rule conditions

A write operation sends data that

fails rule-based validation (e.g., missing required fields or incorrect data types)

A collectionGroup query is missing

corresponding rules for the subcollection path using match /{path=**}/subcollection/{doc}

The user's authentication token has

expired and the app has not refreshed it before making the Firestore call

Custom claims used in security

rules were recently updated but the user's token has not been refreshed to include the new claims

How to fix "Firestore: permission-denied"

Open the Firebase Console, go to Firestore > Rules > Rules Playground. Simulate the exact operation your code performs — specify the collection path, operation type (get, list, create, update, delete), and the auth context. The playground shows exactly which rule matched and why it denied the request.

For read operations, make sure your query includes where clauses that match your rule conditions. If your rule says allow read: if request.auth.uid == resource.data.ownerId, your query must include .where('ownerId', '==', currentUser.uid).

For write operations, verify that the data you are sending matches the rule's validation. Rules can check request.resource.data fields for required values, types, and constraints. A missing or incorrectly typed field will cause a permission denial.

For authentication issues, use onAuthStateChanged to wait for auth to be fully initialized before making Firestore calls. Queries made during the brief moment after page load but before auth state resolves will be treated as unauthenticated. If you use custom claims, call user.getIdToken(true) to force a token refresh after updating claims server-side.

Before
typescript
// Rules require auth but query doesn't wait for auth state
const db = getFirestore();
// This runs before auth resolves!
const snapshot = await getDocs(collection(db, 'userPosts'));
After
typescript
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { getFirestore, collection, query, where, getDocs } from 'firebase/firestore';
const auth = getAuth();
const db = getFirestore();
// Wait for auth to resolve before querying
onAuthStateChanged(auth, async (user) => {
if (user) {
// Query matches rule: allow read if request.auth.uid == resource.data.ownerId
const q = query(
collection(db, 'userPosts'),
where('ownerId', '==', user.uid)
);
const snapshot = await getDocs(q);
snapshot.forEach(doc => console.log(doc.data()));
} else {
console.log('User not signed in');
}
});

Prevention tips

  • Always test rules in the Firebase Rules Playground before deploying — it shows exactly why a request is allowed or denied with the specific rule that matched
  • Use onAuthStateChanged to ensure authentication is fully initialized before making any Firestore calls, preventing queries from running as unauthenticated
  • For collectionGroup queries, add a specific rule at match /{path=**}/subcollection/{doc} — collection-level rules do not automatically apply to group queries
  • After updating custom claims on the server, call user.getIdToken(true) on the client to force a token refresh so the new claims take effect immediately

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm getting 'Firestore: permission-denied' error code when reading documents. My security rules use custom claims for role-based access. The error happens for some users but not others. How do I debug this?

Firebase Prompt

My Firebase app returns [cloud_firestore/permission-denied]. Here are my security rules and the query code: [paste both]. Tell me exactly which rule is blocking the query and fix both the rules and the query to work together.

Frequently asked questions

What is the difference between "Firestore: permission-denied" and "Missing or insufficient permissions"?

They are the same error at different levels. 'permission-denied' is the specific SDK error code, while 'Missing or insufficient permissions' is the human-readable message. Both mean your Firestore security rules blocked the operation. The cause and fix are identical.

Why does my Firestore query fail with permission-denied even when all documents match my rules?

Firestore rules are not filters. Firestore evaluates whether the query could theoretically access unauthorized documents, not whether the actual results would pass. If your rules check a userId field, the query must include a matching .where() clause to structurally prove it only accesses authorized data.

How do I debug Firestore permission-denied errors?

Use the Firebase Console Rules Playground (Firestore > Rules > Rules Playground). It lets you simulate any operation with specific auth context and shows exactly which rule allowed or denied the request. This is the single most reliable debugging tool.

Can expired authentication tokens cause Firestore permission-denied?

Yes. Firebase Auth tokens expire after one hour. The SDK usually refreshes them automatically, but in some cases (offline usage, background tabs), the token may expire. Calling user.getIdToken(true) forces a refresh. Also ensure your code waits for onAuthStateChanged before making Firestore calls.

Do AI code generators frequently cause this Firestore error?

Yes. AI tools like Lovable, Cursor, and V0 commonly generate Firestore queries without matching security rules, or they create permissive development rules that break when tightened for production. Always review both the generated queries and rules together.

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help debugging Firebase errors?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.