From c007435a0484c09b6d1b689028c0d33df3b1d9df Mon Sep 17 00:00:00 2001 From: Priandana Gerdian Date: Fri, 27 Feb 2026 10:12:17 +0800 Subject: [PATCH] fix: skip extensions API check when no extensions are defined When deploying functions without any Firebase Extensions defined, the CLI was unnecessarily checking the firebaseextensions.googleapis.com API and requiring firebaseextensions.instances.list permission. This caused deployment failures for projects that: - Don't use Firebase Extensions at all - Have the API disabled - Don't have the required IAM permissions The fix adds an early return in prepareDynamicExtensions() when no extensions are defined in the function builds, avoiding the unnecessary API calls and permission checks. Fixes deployment errors like: Error: Request to firebaseextensions.googleapis.com returned 403 --- src/deploy/extensions/prepare.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/deploy/extensions/prepare.ts b/src/deploy/extensions/prepare.ts index cf3de21efa2..d066e0a8ac4 100644 --- a/src/deploy/extensions/prepare.ts +++ b/src/deploy/extensions/prepare.ts @@ -171,6 +171,14 @@ export async function prepareDynamicExtensions( const filters = getEndpointFilters(options, functionsConfig); const extensions = extractExtensionsFromBuilds(builds, filters); const projectId = needProjectId(options); + + // Skip extensions API checks if no extensions are defined in the builds. + // This avoids unnecessary API calls and permission errors for projects + // that don't use Firebase Extensions but still deploy functions. + if (Object.keys(extensions).length === 0) { + return; + } + const projectNumber = await needProjectNumber(options); await ensureExtensionsApiEnabled(options); @@ -181,8 +189,8 @@ export async function prepareDynamicExtensions( extensionMatchesAnyFilter(e.labels?.codebase, e.instanceId, filters), ); - if (Object.keys(extensions).length === 0 && haveExtensions.length === 0) { - // Nothing defined, and nothing to delete + if (haveExtensions.length === 0) { + // Nothing to delete return; }