Firebase Hosting 部署失败

修复 firebase deploy --only hosting:CLI 版本、登录过期、public 路径错、Spark 配额。

firebase deploy --only hosting 跑到一半抛 HTTP Error: 400HTTP Error: 401, Request had invalid authentication credentialsFailed to make request to https://firebasehosting.googleapis.com/...Site quota exceeded。Hosting 的部署链路很短,失败基本集中在四件事上:CLI 太旧登录过期firebase.json 里 public 路径写错、以及 Spark 计划配额超限

最快的修法(多数情况能解决):加 --debug 重跑看到真正的报错,然后升级 CLI 并重新认证:

npm install -g firebase-tools@latest
firebase login --reauth
firebase deploy --only hosting --debug

如果还失败,--debug 日志会告诉你属于哪一类。下面把每条错误字符串对应到根因和具体修法。

先判断你属于哪一类

--debug 日志里的字符串和下面对照:

日志里的错误字符串根因看哪一节
Unexpected errorFailed to parse hostCannot read propert...CLI 太旧原因 1
HTTP Error: 401Request had invalid authentication credentialshave you run firebase login?登录过期 / 账号不对原因 2
found 0 files in public、部署”成功”但线上是空白public 路径错原因 3
Site quota exceededQUOTA_EXCEEDEDover its quotaSpark 配额超限原因 4
Invalid hosting configurationSpecified "redirects" config is not validrewrites/redirects 语法错原因 5

按命中率排序的原因

1. CLI 太旧或与项目不匹配

Firebase CLI 每隔几个月就改 API 协议,老版本(特别是 v13 以下)经常对新版能正常处理的情况抛 Unexpected error: ...Failed to parse host 这类含糊错误。截至 2026 年 6 月,firebase-tools 当前在 15.x 这条线上;落后两个或更多大版本就有实际风险。

$ firebase --version
9.22.0   # 太老了——升到最新版(2026 年 6 月为 15.x)

如何判断:你没动过任何配置,却报 Cannot read property 'X' of undefinedUnexpected token in JSON,大概率是 CLI 版本问题。

2. Auth token 过期或换了 Google 账号

CLI 把登录态存在 ~/.config/configstore/firebase-tools.json。token 过期或你切到了别的 Google 账号时,会报 HTTP Error: 401, Request had invalid authentication credentialsFailed to authenticate, have you run firebase login?

如何判断firebase login:list 看当前登录的账号,是不是这个项目所属的那个;或者干脆什么都没有。

3. firebase.json 的 public 路径和 build 产物对不上

public 字段指定被上传的目录。Astro 默认 build 到 dist/、Next.js 静态导出到 out/、Vite 到 dist/,但很多项目沿用了 firebase init 默认的 "public": "public",结果上传的是空目录。

// firebase.json — Astro 项目的典型配置
{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [{ "source": "**", "destination": "/index.html" }]
  }
}

如何判断:部署日志显示 i hosting[project]: found 0 files in public——上传了 0 个文件。部署”成功”了,但线上 URL 是空白或 404。

4. 超出 Spark 免费配额

截至 2026 年 6 月,Spark(免费)计划给每个项目 10 GB Hosting 存储总量、每月 10 GB 数据传输,单文件上限 2 GB。这两个限制失败方式不同:

  • 存储超过 10 GB:新部署被拦下,报 Site quota exceeded / QUOTA_EXCEEDED。注意旧的 release 即使发了新版也仍占着存储,所以长期项目会越积越多。
  • 传输每月超过 10 GB:你的线上站点会被停用,直到下一个计费周期(或升级到 Blaze)——这影响访客,不是部署。

如何判断:Firebase Console -> Hosting -> Usage 标签,看 StorageData transfer 两个数字。

5. rewrites / redirects 语法错误

常见手写错误:sourcedestination 反了、glob 模式 ** 写成 *、或者 redirect 缺了必需的 type(301/302)。CLI 在部署时才校验,所以本地看着没问题。

// 错误示例:缺少必需的 type
"redirects": [
  { "source": "/old", "destination": "/new" }
]
// 正确
"redirects": [
  { "source": "/old", "destination": "/new", "type": 301 }
]

如何判断:日志里出现 Invalid hosting configurationSpecified "redirects" config is not valid

最短修复路径

先拿完整日志,再按”升级 / 重登 / 配置 / 配额”的顺序排。

Step 1:用 --debug 重跑拿到完整堆栈

默认输出会折叠真正的报错。加上 --debug 并存下来:

firebase deploy --only hosting --debug 2>&1 | tee firebase-deploy.log

日志里搜 [ERROR]HTTP Error:,旁边通常就是真正的根因(PERMISSION_DENIED / INVALID_ARGUMENT / QUOTA_EXCEEDED 等)。再用上面的表对号入座。

Step 2:升级 CLI 并重新认证

# 全局升级
npm install -g firebase-tools@latest
firebase --version   # 期望 15.x(2026 年 6 月)

# 原地刷新 token——保留账号,只重新发 token
firebase login --reauth

# 确认当前账号确实拥有这个项目
firebase login:list
firebase projects:list   # 看是不是有这个 project_id

如果 --reauth 还没清掉,就完整执行 firebase logout && firebase login。无头机器上加 --no-localhost,用粘贴 code 的方式代替开浏览器。

Step 3:校验 firebase.json 的 public 指向正确

# 看本地实际 build 出来的产物
ls -la dist/   # 或 out/、build/、public/,看你的框架

# 看 firebase.json 里写的是什么
grep '"public"' firebase.json

两者必须一致。常见框架对照:

框架build 输出目录
Astro (static)dist
Next.js (静态导出)out
Vitedist
Create React Appbuild
Vue CLI / Vite (Vue)dist
SvelteKit (static adapter)build

firebase deploy --only hosting --dry-run 会跑完上传步骤但不真正发布,可以先确认文件数再上线。

Step 4:本地起 emulator 提前发现问题

firebase emulators:start --only hosting
# 在 http://localhost:5000 打开,行为跟生产一致
# rewrites / redirects 配置有问题,emulator 会抛同样的错误

修完配置在 emulator 验证通过,再 deploy。

Step 5:配额超限的应对

如果 Step 1 日志显示 QUOTA_EXCEEDEDSite quota exceeded

  1. Firebase Console -> Hosting -> Usage,看当前的 Storage 和 Transfer 数字。
  2. 临时方案(存储):删除一些历史版本(Hosting -> Release history -> 点旧的 release -> Delete)释放存储,解开下一次部署。
  3. 传输超限:Spark 上没办法重置每月传输计数,只能等下一个计费周期或升级。
  4. 长期方案:升级到 Blaze 按量付费。截至 2026 年 6 月,超出免费额度后 存储约 $0.026/GB·月传输约 $0.15/GB——多数小站点一个月还是几美分。记得设一个 Cloud Billing 预算提醒,Blaze 才不会给你惊喜。

Step 6:rewrites / redirects 语法校验

把 firebase.json 对照 Hosting 配置参考 比对字段名。或者本地用官方 schema 跑校验:

npx ajv-cli validate \
  -s https://raw.githubusercontent.com/firebase/firebase-tools/master/schema/firebase-config.json \
  -d firebase.json

怎么确认修好了

  1. firebase deploy --only hosting 退出码为 0,且打印的文件数不为零,例如 i hosting[project]: file upload complete,随后 + Deploy complete!
  2. 用部署输出里的 Hosting URL(不是缓存标签页),在无痕窗口打开,确认新内容能加载出来。
  3. Firebase Console -> Hosting -> Release history 出现一个时间戳为当前、文件数符合预期的新 release。
  4. 如果你改的是 rewrites/redirects,用 curl -I https://YOUR-SITE.web.app/old 打一个被重定向的路径,确认返回 301/302location 头。

预防建议

  • package.json 的 devDependencies 里 pin firebase-tools 版本(例如 "firebase-tools": "15.20.0"),团队和 CI 永远用同一版。
  • CI 里优先用 service account key 配合 GOOGLE_APPLICATION_CREDENTIALS,而不是 firebase login:ciFIREBASE_TOKEN / login:ci 这套已被官方标记为弃用,会在未来某个大版本里移除。
  • 在 PR 上跑 firebase hosting:channel:deploy preview 预览部署,主分支合并前就能发现 firebase.json 问题。
  • 部署前加一步 firebase emulators:exec "echo ok" --only hosting,配置错的话本地就 fail。
  • 设置 Cloud Billing / Firebase 预算提醒(哪怕没开 Blaze 也能用),在存储或传输到 80% 时邮件提醒。

常见问题

firebase deploy 显示了 “Deploy complete!”,但我的站点是空白的? public 目录是空的或写错了——日志里找 found 0 files in public。把 public 指向真正的 build 产物(distoutbuild)再重新部署。见原因 3。

怎么修 HTTP Error: 401, Request had invalid authentication credentials 你的 token 过期或换了 Google 账号。跑 firebase login --reauth,再用 firebase login:list 确认当前账号拥有这个项目。CI 里用 service account key,别用交互式登录。

我应该用哪个 CLI 版本? 截至 2026 年 6 月,firebase-tools 当前在 15.x 这条线。跑 npm install -g firebase-tools@latest,并在 package.json 里 pin 确切版本,让 CI 和本地一致。

报了 “Site quota exceeded”,一定要付费吗? 不一定。如果是存储超限,去 Hosting -> Release history 删掉旧 release,降回 10 GB 以下即可。如果是每月传输超限,就等下一个计费周期,或升级到 Blaze;Blaze 传输约 $0.15/GB,小站点通常只花几美分。

部署会自动删掉旧版本吗? 不会。旧 release 仍留在 Release history 里,继续占用 10 GB 存储上限。定期清理,否则免费项目迟早会撞到配额。

部署前能先校验 firebase.json 吗? 能——firebase deploy --only hosting --dry-run 会跑完除发布外的所有步骤;emulator(firebase emulators:start --only hosting)能在本地复现 rewrites/redirects 的报错。

相关阅读

标签: #部署 / 托管 #排查 #排查 #Firebase