Firebase Admin error
Error: Could not load the default credentials.
"Could not load the default credentials." is thrown by google-auth-library, which firebase-admin uses, when the Admin SDK needs an access token and finds no Application Default Credentials. It looks, in order, for the GOOGLE_APPLICATION_CREDENTIALS file path, a file made by gcloud auth application-default login, and the metadata server of a Google environment. Vercel is not one of the Google environments the Firebase docs list, so unless you add a key file and set the variable, a Vercel function finds none, and initializeApp() without a credential fails on the first call that needs a token, such as getAuth().getUser() or a Firestore read. Pass credential: cert({...}) built from service account values in server-side Vercel variables, then redeploy. Reproduced with firebase-admin 14.5.0 and google-auth-library 11.3.2 on 2026-10-31.
What does the error look like from Auth and from Firestore?
The sentence is NO_ADC_FOUND in google-auth-library (src/auth/googleauth.ts), thrown after the library tried the environment variable, the well-known file and the metadata server. Through firebase-admin Auth it comes wrapped in an app/invalid-credential error. Through Firestore it is the bare message, and in our run with @google-cloud/firestore 9.4.0 it reached process.on("unhandledRejection") and not the try/catch around the await, so check the function log, not only your catch block. We ran this with initializeApp({ projectId }) and METADATA_SERVER_DETECTION=none, which the gcp-metadata README describes as not pinging the metadata server, so no request left the machine.
getAuth().getUser("abc")
app/invalid-credential: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information."
getFirestore().collection("x").get()
Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.It says "Unable to detect a Project Id in the current environment" instead
With initializeApp() and no options, and neither GOOGLE_CLOUD_PROJECT nor GCLOUD_PROJECT set, getUser, verifyIdToken and a Firestore read all printed "Unable to detect a Project Id in the current environment" in our run, before the credentials error. firebase-admin reads those two variables for the project ID. Adding projectId to initializeApp() moved the error on to "Could not load the default credentials", which is the same missing credential seen one step later.
How do I initialize firebase-admin on Vercel without a key file?
The Firebase docs recommend Application Default Credentials in Google environments such as Cloud Run and Cloud Functions for Firebase, and show a service account key file, set through GOOGLE_APPLICATION_CREDENTIALS, for other environments. firebase-admin also accepts the values directly through cert(), which suits a host where you cannot place a file. On Vercel, pass the service account values from environment variables to cert(), and keep them out of any NEXT_PUBLIC_ name, which Next.js copies into the browser bundle. If cert() then throws about the key, see the private key error.
import { cert, getApps, initializeApp } from 'firebase-admin/app'
if (!getApps().length) {
initializeApp({
credential: cert({
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
}),
})
}Checklist
How to fix it, then check the fix
- 01Find every place the Admin SDK is initialized and what credential it gets:
grep -rnE "initializeApp\(|applicationDefault|cert\(|GOOGLE_APPLICATION_CREDENTIALS" --exclude-dir=node_modules --exclude-dir=.next . - 02Take projectId, clientEmail and privateKey from the service account JSON of your Firebase project. The Firebase docs warn that service account keys need extremely high security awareness, so keep the file out of git.
- 03Add the three values in Vercel for each environment that runs the server code, with no NEXT_PUBLIC_ prefix:
vercel env add FIREBASE_PROJECT_ID production vercel env add FIREBASE_CLIENT_EMAIL production vercel env add FIREBASE_PRIVATE_KEY production - 04Pass credential: cert({...}) to initializeApp(), guarded with getApps() so a hot reload or a second import does not initialize twice.
- 05Redeploy: Vercel applies changed variables only to new deployments. Then call one Admin SDK method that needs a token, such as getAuth().getUser(uid), from the deployed route: the function log no longer shows the credentials error.
Related
Related guides
Sources
Official docs behind this checklist
- Firebase, Add the Firebase Admin SDK to your server
- Google Cloud, How Application Default Credentials works
- google-auth-library-nodejs, src/auth/googleauth.ts
- gcp-metadata, README (METADATA_SERVER_DETECTION)
- firebase-admin-node, src/app/lifecycle.ts
- firebase-admin-node issue 738
- Next.js, Environment variables
- Vercel, Environment variables
Browse all launch guides · Read resources · How to make and check your next change
FAQ
FAQ for builders before launch
Can I keep using applicationDefault() on Vercel?
Only if GOOGLE_APPLICATION_CREDENTIALS points to a key file that exists inside the function, which means shipping the key in your build output. The Firebase docs recommend that variable for non-Google environments; the cert() route above keeps the key in an environment variable instead.
Does the error also happen on Google Cloud?
It can. A 2019 firebase-admin-node issue (738) reports it from a Firestore query in a Cloud Function after an upgrade; the maintainer suspected old versions of dependencies such as gcp-metadata, and the reporter said it stopped after updating two @google-cloud packages.
Should the service account go in a NEXT_PUBLIC_ variable?
No. Next.js inlines NEXT_PUBLIC_ variables into the JavaScript sent to the browser, so the private key would be readable by every visitor. Use plain names and read them only in server code.