firebase / firebase/firebase-tools
Emulator hangs trying to get credentials from cloud with demo server
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.3k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 84
Description
### [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`:
```typescript
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:
```typescript
let credentialEnv: Record = {};
if (!Constants.isDemoProject(this.args.projectId)) {
credentialEnv = await getCredentialsEnvironment(
this.args.account,
this.logger,
"functions",
);
}
```
Contributor guide
Assessment
This issue has not been assessed yet.