[REQUIRED] Environment info
firebase-tools: Reproduces on 14.2.1, 13.x latest, and 13.29 (all three tested).
Platform: macOS, Node 20, pnpm.
[REQUIRED] Test case
firebase.json declares Firestore as an array of database-scoped entries (the multi-DB shape from the docs):
{
"firestore": [
{ "database": "(default)", "rules": "firestore.rules", "indexes": "firestore.indexes.json" },
{ "database": "devdb", "rules": "firestore.rules", "indexes": "firestore.indexes.json" }
]
}
Local firestore.rules has at least one rule that differs from the live ruleset on either database.
[REQUIRED] Steps to reproduce
Reproducer 1 — silent no-op:
firebase deploy --only firestore:rules --project <project-id>
Reproducer 2 — scoped form crashes:
firebase deploy --only 'firestore:rules:(default)' --project <project-id>
Reproducer 3 — debug log:
firebase deploy --only firestore:rules --debug --project <project-id> 2>&1 | tee /tmp/rules-debug.log
[REQUIRED] Expected behavior
- Reproducer 1 should deploy the rules file to every database in the array whose rules differ from live, printing one
released rules ... to cloud.firestore (<db-name>) line per release.
- Reproducer 2 should be the way to deploy rules to a single database in the array — either work, or fail with an actionable error like
firestore:rules:<db-name> is not a recognized filter; use firestore:<db-name> to deploy rules + indexes for that database.
- At minimum, when the planner produces an empty rules changeset against a non-empty rules diff vs. live, the CLI should print
i firestore: rules unchanged on all databases so the operator knows nothing was uploaded. The silent no-op is the most operationally dangerous of the three — indistinguishable from a successful deploy.
[REQUIRED] Actual behavior
Reproducer 1 (silent no-op). Output is just:
=== Deploying to '<project-id>'...
i deploying firestore
✔ Deploy complete!
No rules are released. Live ruleset unchanged. Exit 0. The --debug log shows only datastore.indexes.* IAM permissions being checked, then i deploying firestore, then ✔ Deploy complete!. No rules-related lifecycle lines anywhere — the rules planner is producing an empty changeset against the multi-DB array form.
Reproducer 2 (scoped form crash). Output is:
i firestore: deploying indexes...
TypeError: Cannot read properties of undefined (reading 'map')
at deployIndexes (.../firebase-tools/lib/deploy/firestore/deploy.js:24:38)
Two problems visible: (a) the :rules filter isn't honored — the CLI still tries the indexes path; (b) when filtered to one DB, the indexes config it receives is undefined and it crashes before reaching the rules step.
Working incantation (current workaround). --only firestore:(default) (no :rules) deploys rules + indexes for that single DB:
i firestore: reading indexes from firestore.indexes.json...
i cloud.firestore: checking firestore.rules for compilation errors...
✔ cloud.firestore: rules file firestore.rules compiled successfully
i firestore: deploying indexes...
i firestore: uploading rules firestore.rules...
✔ firestore: deployed indexes in firestore.indexes.json successfully for (default) database
✔ firestore: released rules firestore.rules to cloud.firestore
✔ Deploy complete!
This works, but force-co-deploys indexes — there's no way to deploy only the rules, and it doesn't iterate the array (deploys to one DB at a time, requires running the command once per database).
Versions tested:
firebase-tools |
--only firestore:rules |
--only firestore:rules:(default) |
--only firestore:(default) |
14.2.1 |
silent no-op |
TypeError: ... map |
✓ works |
13.x (latest) |
silent no-op |
not tested |
not tested |
13.29 |
silent no-op |
not tested |
not tested |
Suggested triage. Most likely the rules-deploy planner in lib/deploy/firestore/ doesn't iterate the array-shape firestore config and instead expects the legacy single-object shape, falling back to "no databases to deploy rules to" when it sees the array. The scoped-filter crash in deployIndexes looks like a separate bug where the per-DB-scoped path skips the indexes config load.
Happy to provide a full debug log if it'd help triage.
[REQUIRED] Environment info
firebase-tools: Reproduces on
14.2.1,13.xlatest, and13.29(all three tested).Platform: macOS, Node 20, pnpm.
[REQUIRED] Test case
firebase.jsondeclares Firestore as an array of database-scoped entries (the multi-DB shape from the docs):{ "firestore": [ { "database": "(default)", "rules": "firestore.rules", "indexes": "firestore.indexes.json" }, { "database": "devdb", "rules": "firestore.rules", "indexes": "firestore.indexes.json" } ] }Local
firestore.ruleshas at least one rule that differs from the live ruleset on either database.[REQUIRED] Steps to reproduce
Reproducer 1 — silent no-op:
Reproducer 2 — scoped form crashes:
Reproducer 3 — debug log:
[REQUIRED] Expected behavior
released rules ... to cloud.firestore (<db-name>)line per release.firestore:rules:<db-name> is not a recognized filter; use firestore:<db-name> to deploy rules + indexes for that database.i firestore: rules unchanged on all databasesso the operator knows nothing was uploaded. The silent no-op is the most operationally dangerous of the three — indistinguishable from a successful deploy.[REQUIRED] Actual behavior
Reproducer 1 (silent no-op). Output is just:
No rules are released. Live ruleset unchanged. Exit 0. The
--debuglog shows onlydatastore.indexes.*IAM permissions being checked, theni deploying firestore, then✔ Deploy complete!. No rules-related lifecycle lines anywhere — the rules planner is producing an empty changeset against the multi-DB array form.Reproducer 2 (scoped form crash). Output is:
Two problems visible: (a) the
:rulesfilter isn't honored — the CLI still tries the indexes path; (b) when filtered to one DB, the indexes config it receives isundefinedand it crashes before reaching the rules step.Working incantation (current workaround).
--only firestore:(default)(no:rules) deploys rules + indexes for that single DB:This works, but force-co-deploys indexes — there's no way to deploy only the rules, and it doesn't iterate the array (deploys to one DB at a time, requires running the command once per database).
Versions tested:
firebase-tools--only firestore:rules--only firestore:rules:(default)--only firestore:(default)14.2.1TypeError: ... map13.x(latest)13.29Suggested triage. Most likely the rules-deploy planner in
lib/deploy/firestore/doesn't iterate the array-shapefirestoreconfig and instead expects the legacy single-object shape, falling back to "no databases to deploy rules to" when it sees the array. The scoped-filter crash indeployIndexeslooks like a separate bug where the per-DB-scoped path skips the indexes config load.Happy to provide a full debug log if it'd help triage.