Skip to content

Emulator hangs trying to get credentials from cloud with demo server #10398

@kevmoo

Description

@kevmoo

[REQUIRED] Environment info

firebase-tools: 15.15.0 (Current source version)

Platform: macOS

[REQUIRED] Test case

A Firebase project configured with the Functions emulator (and optionally Hosting). The project is run in a local development environment (not on Google Compute Engine) without the GOOGLE_APPLICATION_CREDENTIALS environment variable set and without active Application Default Credentials (ADC) configured via gcloud auth application-default login.

[REQUIRED] Steps to reproduce

  1. Initialize a project with the Functions emulator.
  2. Ensure no GCP credentials are set in your local environment.
  3. Run firebase emulators:start.
  4. Observe that the emulator suite hangs indefinitely (or for a very long time) during the startup sequence, specifically after printing the startup banner but before fully initializing the services.

[REQUIRED] Expected behavior

The emulator should start up quickly. If credentials are not found, it should fall back gracefully or fail fast. For local-only testing scenarios (such as using a demo- project ID), it should avoid making blocking network calls to resolve cloud credentials.

[REQUIRED] Actual behavior

The emulator hangs at the beginning of FunctionsEmulator.start().

By adding debug logging, we traced the hang to line 452 in src/emulator/functionsEmulator.ts:

const credentialEnv = await getCredentialsEnvironment(this.args.account, this.logger, "functions");

This method calls auth.getApplicationDefault() from the google-auth-library. Because no credentials are found in the environment, the library attempts to discover them by polling the Google Cloud Metadata Server (which only exists when running inside GCP). In a local environment, this request hangs waiting for a network timeout, which can take minutes, making the CLI appear frozen.

Suggested Resolution

For projects intended solely for local emulation (i.e., those with IDs starting with demo-), we can safely skip this credential check. Adding the following guard in FunctionsEmulator.start() resolved the issue for us:

let credentialEnv: Record<string, string> = {};
if (!Constants.isDemoProject(this.args.projectId)) {
  credentialEnv = await getCredentialsEnvironment(
    this.args.account,
    this.logger,
    "functions",
  );
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions