firebase-admin-node icon indicating copy to clipboard operation
firebase-admin-node copied to clipboard

Firestore Index errors are missing the details field. They do not tell you the index creation URL

Open oconnorjoseph opened this issue 2 months ago • 7 comments

[REQUIRED] Step 2: Describe your environment

  • Operating System version: Google Cloud Run (Cloud Functions Gen 2), Node.js 22 base image: us-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22:nodejs22_20251005_22_20_0_RC00
  • Firebase SDK version: firebase-admin 13.5.0; firebase-functions 6.1.2
  • Firebase Product: Firestore
  • Node.js version: 22.20.0 (nodejs22 runtime)
  • NPM version: N/A (managed Cloud Run runtime)

[REQUIRED] Step 3: Describe the problem

When a Firestore query in a deployed Cloud Functions Gen 2 service (Cloud Run) requires a composite index that does not exist, the error object logged by the function lacks the expected “This query requires an index...” message in the structured log’s jsonPayload.details field. The code is 9 (FAILED_PRECONDITION), but details is an empty string. This makes it difficult to understand that the failure is a missing index and removes the direct link to create the index.

In past behavior (including our historical logs), errors for missing indexes include a helpful sentence and direct Console link (e.g., “You can create it here: …”). In the current environment, that message is missing from jsonPayload.details.

This seems related to the error shape surfaced by the Admin SDK / @google-cloud/firestore under Node 22 on Cloud Run and how it’s serialized into structured logs.

Steps to reproduce:

  1. Deploy a minimal Cloud Function Gen 2 (callable or HTTP) using firebase-admin 13.5.0 on Node 22.
  2. Inside the handler, run a Firestore query that requires a composite index which does not exist. For example, a collectionGroup query with a filter and an orderBy across different fields.
  3. Trigger the function so the query runs without the index created.
  4. Inspect Cloud Run logs (run.googleapis.com/stderr or request logs). Observe jsonPayload.code: 9 and jsonPayload.details: "" (empty).

Expected behavior:

  • The error should include a message in details indicating a missing index and provide the “You can create it here:” link, consistent with Firestore documentation and prior behavior.
    • Example of expected message (from prior logs): “Error: 9 FAILED_PRECONDITION: The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/.../firestore/indexes?create_composite=...”

Actual behavior:

  • jsonPayload.code is 9 but jsonPayload.details is an empty string, removing the actionable guidance.
  • Example from our production logs:
{
  "resource": { "type": "cloud_run_revision", "labels": { "service_name": "callable-auth-findowner", "location": "us-central1" } },
  "severity": "ERROR",
  "jsonPayload": {
    "details": "",
    "metadata": { "x-debug-tracking-id": ["16904469887567850844;o=1"] },
    "code": 9
  },
  "labels": {
    "deployment-callable": "true",
    "firebase-functions-codebase": "c-auth-findowner",
    "revision_name": "callable-auth-findowner-00199-nod",
    "run.googleapis.com/base_image_versions": "us-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22:nodejs22_20251005_22_20_0_RC00"
  },
  "timestamp": "2025-10-16T21:20:07.065372Z",
  "logName": "projects/blumint-development/logs/run.googleapis.com%2Fstderr"
}

Relevant Code:

// Minimal reproduction (TypeScript)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp();

export const findOwnerRepro = functions.https.onCall(async (data) => {
  const db = admin.firestore();
  const email = String(data.email || '');

  try {
    // Example that typically requires a composite index if none exists:
    // collectionGroup + equality filter + orderBy on a different field
    const snap = await db
      .collectionGroup('UserPrivate')
      .where('email', '==', email)
      .orderBy('deleted')     // differing field -> composite index requirement
      .limit(1)
      .get();

    return snap.empty ? null : snap.docs[0]!.data();
  } catch (error) {
    // Structured logs show code: 9 but jsonPayload.details: "" (blank)
    console.error('Query failed', error);
    throw new functions.https.HttpsError('internal', 'Query failed');
  }
});

Additional notes:

  • Historically, our logs did include the helpful “You can create it here” link for missing index errors. With Node 22 on Cloud Run, jsonPayload.details is blank even though code is 9.
  • If this is an expected change in error shape or serialization, guidance on where to reliably retrieve the missing-index message (e.g., error.message) in structured logging would be helpful. Otherwise, restoring the helpful text in details would greatly improve debuggability.
  • This same issue has been encountered on StackOverflow several times but not reported: https://stackoverflow.com/questions/78545358/firestore-query-error-error-9-failed-precondition, https://stackoverflow.com/questions/77680486/get-the-full-error-in-nextjs-14-server-components

oconnorjoseph avatar Oct 16 '25 21:10 oconnorjoseph

I found a few problems with this issue:

  • I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
  • This issue does not seem to follow the issue template. Make sure you provide all the required information.

google-oss-bot avatar Oct 16 '25 21:10 google-oss-bot

➕ 1️⃣

builtbyjavi avatar Oct 16 '25 21:10 builtbyjavi

Update: it seems that composite indexes do in fact populate the details field. Single-field indexes still do not.

oconnorjoseph avatar Oct 16 '25 23:10 oconnorjoseph

➕ 2

shaffy9633 avatar Oct 20 '25 06:10 shaffy9633

Assigning @cherylEnkidu to take a look (as discussed offline)

dconeybe avatar Oct 20 '25 15:10 dconeybe

Thank you for reporting this issue. I am able to reproduce it on my end. I will reach out to the responsible team to take another look.

cherylEnkidu avatar Oct 21 '25 15:10 cherylEnkidu

Hi @dconeybe @cherylEnkidu, what is the status of this issue? We would very much appreciate a fix.

oconnorjoseph avatar Dec 03 '25 00:12 oconnorjoseph

the singlefield indexes are still giving problemss...

shaffy9633 avatar Dec 11 '25 11:12 shaffy9633

Hi, I am following up with the backend team. Sorry for the delay.

cherylEnkidu avatar Dec 11 '25 16:12 cherylEnkidu