firebase-admin-node: [Firestore] hangs indefinitely

[REQUIRED] Step 2: Describe your environment

  • Operating System version: macOS Big Sur v11.2
  • Firebase SDK version: 8.13.0
  • Firebase Product: Firestore
  • Node.js version: v15.8.0
  • NPM version: 7.5.0

[REQUIRED] Step 3: Describe the problem

Steps to reproduce:

Doing anything with Firestore hangs indefinitely. After testing with resolutions of @grpc/grpc-js,

  • <0.6.0: returns “Protocol https: unsupported”
  • 0.6.0: API returns {"error":{}}
  • >0.6.0: hangs indefinitely (returns an error message like this:)
node:events:355
      throw er; // Unhandled 'error' event
      ^

Error: 14 UNAVAILABLE: No connection established
    at Object.callErrorFromStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call.js:30:26)
    at Object.onReceiveStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client.js:328:49)
    at Object.onReceiveStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:304:181)
    at Http2CallStream.outputStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call-stream.js:114:27)
    at Http2CallStream.maybeOutputStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call-stream.js:153:22)
    at Http2CallStream.endCall (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call-stream.js:140:18)
    at Http2CallStream.cancelWithStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call-stream.js:442:14)
    at ChannelImplementation.tryPick (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/channel.js:232:32)
    at ChannelImplementation._startCallStream (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/channel.js:262:14)
    at Http2CallStream.start (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call-stream.js:419:22)
    at BaseStreamingInterceptingCall.start (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:276:19)
    at ServiceClientImpl.makeServerStreamRequest (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client.js:311:14)
    at ServiceClientImpl.<anonymous> (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/make-client.js:92:19)
    at /Users/ryanccn/firebase/node_modules/@google-cloud/firestore/build/src/v1/firestore_client.js:201:29
    at /Users/ryanccn/firebase/node_modules/google-gax/build/src/streamingCalls/streamingApiCaller.js:38:28
    at /Users/ryanccn/firebase/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
Emitted 'error' event on ClientReadableStreamImpl instance at:
    at Object.onReceiveStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client.js:328:28)
    at Object.onReceiveStatus (/Users/ryanccn/firebase/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:304:181)
    [... lines matching original stack trace ...]
    at /Users/ryanccn/firebase/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
    at Object.request (/Users/ryanccn/firebase/node_modules/google-gax/build/src/streamingCalls/streaming.js:105:36) {
  code: 14,
  details: 'No connection established',
  metadata: Metadata { internalRepr: Map(0) {}, options: {} }
}

Relevant Code:

http://github.com/leerob/nextjs-vercel-firebase

// lib/firebase.js

import admin from 'firebase-admin';

try {
  admin.initializeApp({
    credential: admin.credential.cert({
      project_id: process.env.FIREBASE_PROJECT_ID,
      private_key: process.env.FIREBASE_PRIVATE_KEY,
      client_email: process.env.FIREBASE_CLIENT_EMAIL
    }),
    databaseURL: 'https://ryanccn-dev-36130-default-rtdb.firebaseio.com/'
  });
} catch (error) {
  /*
   * We skip the "already exists" message which is
   * not an actual error when we're hot-reloading.
   */
  if (!/already exists/u.test(error.message)) {
    // eslint-disable-next-line no-console
    console.error('Firebase admin initialization error', error.stack);
  }
}

export default admin.firestore();

(This is a Next.js API route)

// pages/api/city/[name].js

import firebase from '../../../lib/firebase';

export default (req, res) => {
  console.log()
  firebase
    .collection('cities')
    .doc(req.query.name)
    .get()
    .then((doc) => {
      res.json(doc.data());
    })
    .catch((error) => {
      res.json({ error });
    });
};

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 26 (4 by maintainers)

Most upvoted comments

Note that you can turn on additional logging by setting the following environment variables:

GRPC_VERBOSITY= DEBUG GRPC_TRACE=all

This should show extensive logging output and might point us to the root cause.

Just in case it’s useful to anyone that comes across this issue, I also had the problem with the connection timing out. After turning on additional logging, as recommended by @schmidt-sebastian, I saw firebase-admin was trying to connect to the host set in the FIRESTORE_EMULATOR_HOST environment variable. Removing it (or setting it to an empty string) fixed it.

@ryanccn hello, do you fixed this problem? I also used proxy,I’m in china.

No… I’ve stopped using Firebase. But I would certainly like to see this problem solved 😇

I had the same issue. docRef.set() and .get() methods timing out and getting error 14 messages.

Firebase emulator was setup with: export FIRESTORE_EMULATOR_HOST="localhost:8000" in cli initially.

Using extra logs - thank you @schmidt-sebastian!

GRPC_VERBOSITY=DEBUG
GRPC_TRACE=all

I saw that admin sdk was trying to access port 8000 without emulators running.

Removing it in CLI resolved it. Thanks @lnoir


Setting FIRESTORE_EMULATOR_HOST is currently the recommended (only?) way in the firebase admin sdk docs to enable the emulator. This can cause issues if you run tests with the emulator and set the ENVAR using CLI and don’t remember to remove it. - It is fixed by setting FIRESTORE_EMULATOR_HOST programmatically in a beforeAll and removing it in an afterAll

Maybe having .useEmulator() in the admin sdk would be a better dev experience:

export const db =
  process.env.NODE_ENV === 'production' ? admin.firestore() : admin.firestore().useEmulator(port);

At the same time everything is working as it is intended as far as I can tell.

I am also experiencing the same issue, any requests to firebase through proxy, hand indefinitely then timeout after 60000ms

Upon further reading of the above issue. I think I am the victim of corporate malware. This is a work MacBook and subsequently has Netskope and god knows what else monitoring and messing with SSL traffic. I added export NODE_TLS_REJECT_UNAUTHORIZED=0 and this got me further down the road. I am going to run this on a non-work regulated Mac; if that works then it’s pretty obvious where the issue lies. Not sure if there is a fix for it though as policy restricts me from disabling the corporate malware.

Are there other ways to authenticate the firebase admin client if there are no workarounds available? As it seems the issue here is some software between my app and the internet is tampering with the cert.

I’m having a similar issue.

When I follow the instructions found here: https://firebase.google.com/docs/admin/setup I get the same Error: 14 UNAVAILABLE: No connection established after about a 60-second wait.

I have created a service account and have the resulting json file available to my node project.

This is a very, very simple node app that just tries to auth and get a document from firestore. It uses…

node 12.19.0 (have also tried 15.x)
firebase-admin: ^9.4.2

I am just performing a simple get on a document that exists in a collection that exists (very similar to the code above). I have used firestore successfully in the past with node without issue.

NOTE: In the code below I preset the GOOGLE_APPLICATION_CREDENTIALS to the serviceAccount JSON. I have also tried to import the file and pass it to the creds function. Both have the same issue.

import admin from 'firebase-admin';

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: 'https://project-name.firebaseio.com', // project-name subbed for my specific project
});

const db = admin.firestore();

export const getDoc = async (): Promise<void> => {

  try {
    const dbRef = db.collection('collection'); // collection subbed for my existing collection
    const result = await dbRef.doc('doc-id').get(); // doc-id subbed for an existing doc-id
    console.log(result);
  } catch (err) {
    console.error("error connecting", err);
  }
};