firebase deploy --only hosting 跑到一半抛 HTTP Error: 400、HTTP Error: 401, Request had invalid authentication credentials、Failed 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 error、Failed to parse host、Cannot read propert... | CLI 太旧 | 原因 1 |
HTTP Error: 401、Request had invalid authentication credentials、have you run firebase login? | 登录过期 / 账号不对 | 原因 2 |
found 0 files in public、部署”成功”但线上是空白 | public 路径错 | 原因 3 |
Site quota exceeded、QUOTA_EXCEEDED、over its quota | Spark 配额超限 | 原因 4 |
Invalid hosting configuration、Specified "redirects" config is not valid | rewrites/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 undefined 或 Unexpected token in JSON,大概率是 CLI 版本问题。
2. Auth token 过期或换了 Google 账号
CLI 把登录态存在 ~/.config/configstore/firebase-tools.json。token 过期或你切到了别的 Google 账号时,会报 HTTP Error: 401, Request had invalid authentication credentials 或 Failed 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 标签,看 Storage 和 Data transfer 两个数字。
5. rewrites / redirects 语法错误
常见手写错误:source 和 destination 反了、glob 模式 ** 写成 *、或者 redirect 缺了必需的 type(301/302)。CLI 在部署时才校验,所以本地看着没问题。
// 错误示例:缺少必需的 type
"redirects": [
{ "source": "/old", "destination": "/new" }
]
// 正确
"redirects": [
{ "source": "/old", "destination": "/new", "type": 301 }
]
如何判断:日志里出现 Invalid hosting configuration 或 Specified "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 |
| Vite | dist |
| Create React App | build |
| 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_EXCEEDED 或 Site quota exceeded:
- Firebase Console -> Hosting -> Usage,看当前的 Storage 和 Transfer 数字。
- 临时方案(存储):删除一些历史版本(Hosting -> Release history -> 点旧的 release -> Delete)释放存储,解开下一次部署。
- 传输超限:Spark 上没办法重置每月传输计数,只能等下一个计费周期或升级。
- 长期方案:升级到 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
怎么确认修好了
firebase deploy --only hosting退出码为0,且打印的文件数不为零,例如i hosting[project]: file upload complete,随后+ Deploy complete!。- 用部署输出里的 Hosting URL(不是缓存标签页),在无痕窗口打开,确认新内容能加载出来。
- Firebase Console -> Hosting -> Release history 出现一个时间戳为当前、文件数符合预期的新 release。
- 如果你改的是 rewrites/redirects,用
curl -I https://YOUR-SITE.web.app/old打一个被重定向的路径,确认返回301/302和location头。
预防建议
- 在
package.json的 devDependencies 里 pin firebase-tools 版本(例如"firebase-tools": "15.20.0"),团队和 CI 永远用同一版。 - CI 里优先用 service account key 配合
GOOGLE_APPLICATION_CREDENTIALS,而不是firebase login:ci。FIREBASE_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 产物(dist、out 或 build)再重新部署。见原因 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 的报错。