Supabase

Fix Firebase 'Invalid site key or not loaded in api.js'

Trace the two Enterprise script loaders, confirm which Firebase release contains the repair, and distinguish a stale SDK from a genuine key configuration problem.

Mahdi Ben RhoumaMahdi Ben Rhouma
7 min read

TL;DR#

When Firebase Auth and App Check both use reCAPTCHA Enterprise, an older SDK can reuse the wrong Enterprise script instance and throw Invalid site key or not loaded in api.js. The two SDK loaders were repaired in PR #9991. Firebase 12.15.0 includes both changes. Upgrade an affected older installation, rebuild it, and check the browser's loaded scripts before changing protection settings. A correctly installed SDK still needs valid project configuration.

The exact error in issue #9405 was:

text
Uncaught Error: Invalid site key or not loaded in api.js: SITE_KEY

The report named Firebase 12.0.0, Chrome, Windows 11 and a Next.js app. Phone sign-in failed with App Check's Enterprise provider and Auth's reCAPTCHA protection configured together. Setting the Auth web key to None changed the behaviour, but that observation did not prove that the original key was invalid.

This article uses class C documentary verification: upstream source, changelogs, release notes and registry metadata checked on 13–14 October 2026. No hosted reCAPTCHA exchange, SMS delivery or account sign-in was tested here.

Why it happens#

The PR identifies two separate loading defects. Auth checked whether window.grecaptcha.enterprise existed. App Check could already have created that object, so Auth skipped downloading its own Enterprise script. Auth needed a script initialised with its configured site key in the render parameter; the existing object alone did not establish that readiness.

Auth's repair initiates its own download and waits for a named global callback supplied through the script URL's onload parameter. The PR explains why neither the ordinary script load event nor grecaptcha.ready reliably indicated that the relevant instance was initialised when multiple Enterprise scripts were present.

App Check had a second defect. It explicitly rendered its Enterprise widget but omitted the corresponding render=explicit URL parameter. The fix adds that parameter. Both changes matter: moving one initialisation call or hand-inserting a script does not implement the complete upstream repair.

The message refers to a reCAPTCHA site key, which serves a different purpose from Firebase's apiKey. For the latter's API restrictions and data-access protections, see the Firebase public API-key guide. Rotating that Firebase identifier does not apply the loader fix.

Fix#

1. Establish which SDK the application actually installs#

Run this in the application package that builds the browser code:

bash
npm ls firebase @firebase/auth @firebase/app-check --all

npm documents that this lists installed versions and the logical dependency tree, including nested matches. Look for older copies pulled in through another package, as well as the top-level Firebase dependency. A version range in package.json is insufficient evidence of the version installed in the build environment.

Firebase's release notes for 12.15.0, dated 16 June 2026, explicitly list the Enterprise conflict repair under both Authentication and App Check. The registry entry maps that umbrella package to:

PackageVersion containing this repair
firebase12.15.0
@firebase/auth1.13.3
@firebase/app-check0.12.0

The Auth changelog and App Check changelog each link the same fix. The PR merged on 29 May; that merge date differs from the release date. These records establish a shipped repair, beyond merely finding a closed issue.

2. Upgrade the affected older installation#

For a project still using an older 12.x SDK, this pins the confirmed fixed release:

bash
npm install firebase@12.15.0 --save-exact

Re-run the dependency inspection, then rebuild and redeploy through the application's existing workflow. Include the updated manifest and lockfile in that deployment. The pin provides a specific verified target; it is not a recommendation to downgrade an application already using a newer supported release. For such an application, investigate its resolved dependency paths and deployed code first.

Updating Auth alone leaves the older App Check loader unchanged. Updating a server package also does not update a separately loaded browser CDN script. Keep the browser's Firebase product imports on a consistent SDK release and inspect the actual delivery method used by your app.

If an old tutorial's default import now fails with Cannot read properties of undefined (reading 'apps'), use the modular-versus-compat import fix. That startup failure has a separate cause and prevents the phone flow from reaching this reCAPTCHA code.

3. Inspect the reCAPTCHA scripts on the failing page#

Open browser developer tools on the deployed sign-in page, reload with Network recording enabled, and attempt the same phone operation. This console snippet lists reCAPTCHA script elements and their relevant parameters:

js
console.table(
  Array.from(document.scripts)
    .filter((script) => /\/recaptcha\/(enterprise|api)\.js/.test(script.src))
    .map((script) => {
      const url = new URL(script.src, document.baseURI);
      return {
        script: url.origin + url.pathname,
        render: url.searchParams.get("render"),
        onload: url.searchParams.get("onload"),
      };
    })
);

The fixed App Check source loads Enterprise with render set to explicit. The fixed Auth source appends its site key and the onFirebaseAuthREInstanceReady callback. These are source-derived indicators for this release, rather than recorded output from your project. Inspect Network failures too: a script element's presence does not prove its request succeeded or its callback ran. Let the SDK manage those callbacks; manually injecting another script is not the prescribed repair.

Verify the fix#

Check the installed dependency tree, the deployed browser bundle and the hosted sign-in result separately. For the browser bundle, add this temporary diagnostic to the existing Firebase client module:

js
import { SDK_VERSION } from "firebase/app";
 
console.info("Firebase JS SDK loaded by this module:", SDK_VERSION);

SDK_VERSION is public. It identifies the SDK imported by that module; it does not independently establish which Auth or App Check copy another bundle or script uses. Combine it with the dependency tree and script inspection. A successful local install does not prove that the deployed page received the new build.

Repeat the phone sign-in attempt with the project's intended protections retained. Check whether the invalid-site-key error disappears, whether the Auth request succeeds, and whether the confirmation flow completes. Record a changed error separately: passing script initialisation does not guarantee SMS delivery or successful verification.

If startup instead throws getProvider of undefined from getFirestore, check that getFirestore receives the FirebaseApp. Passing the configuration object there fails before this Enterprise interaction and needs its own argument correction.

One email a month — the latest explained errors

What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.

When the fixed loaders still reject the configuration#

Check App Check registration and Auth settings independently. Firebase's Enterprise App Check instructions require a score-based web key, the app's domains, and registration of that key for the web app. Initialise App Check early, before accessing Firebase services, using the registered key. A matching-looking string in another console screen is not proof of that registration.

Phone Auth documentation also requires an allowed domain and the appropriate verifier setup. An App Check provider is not the Auth application verifier. For projects using SMS defense, Identity Platform documents that audit-mode fallback on web uses reCAPTCHA v2 and needs a RecaptchaVerifier passed to the phone operation. Diagnose those requirements against the mode actually configured.

The original issue's None setting and later disable-protection workaround changed the protected path. They should not be treated as proof that Enterprise is fundamentally incompatible with Auth. Start with the released SDK repair, confirm that the browser uses it, and use the current project configuration and observed network failure to guide any remaining investigation.

Frequently Asked Questions

|

Have more questions? Contact us

Still stuck? Paste your error.

Paste the error message or stack trace — we check it against every fix and tool on the site.

Matching happens in your browser. When you search, a cleaned error signature is sent so we can spot errors we do not cover yet — never the raw text, your IP address or your e-mail. Do not paste passwords or keys. Details

Written by

Mahdi Ben Rhouma
Mahdi Ben Rhouma

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote