# Firebase 一个错误负载让已上架的 iOS 应用集体崩溃

**Summary:** Firebase Analytics 返回了错误格式的负载，导致已发布的 iOS 应用在启动时崩溃，且缓存的错误响应持续了长达四小时。我认为非必要的遥测功能不应有权限阻止应用启动。

- Canonical: https://markhuang.ai/zh/news/firebase-payload-crashed-released-ios-apps
- Language: zh-CN
- Author: [Mark Huang](https://markhuang.ai/about)
- Published: 2026-09-29
- Section: News
- Tags: Firebase, iOS, 移动 SDK, 应用可靠性, Google Analytics
- Source: [Gergely Orosz on X](https://twitter.com/GergelyOrosz/status/2104825886922911981)
- License: https://creativecommons.org/licenses/by-nc/4.0/

---

![一个格式错误的数据流从云服务扩散，导致一片智能手机崩溃](https://cdn.markhuang.ai/news/firebase-payload-crashed-released-ios-apps/hero.webp)

*移动 SDK 的危险之处不仅在于应用内嵌的代码，更在于厂商发布后仍能改变的实时行为。*

2026 年 9 月 29 日，Gergely Orosz [指出了一起 Firebase 故障](https://twitter.com/GergelyOrosz/status/2104825886922911981)，导致使用其 Analytics SDK 的 iOS 应用纷纷崩溃。这份 [Firebase issue](https://github.com/firebase/firebase-ios-sdk/issues/16728) 的描述更精确：一位开发者在头 18 分钟内就看到了 56 次崩溃，影响 56 名用户，涉及四个已发布版本——期间没有推送过任何应用更新。

出问题的是服务端响应。Google 后来承认，一个格式错误的 payload 导致应用在启动时崩溃。在我看来，Firebase Analytics 此时的表现根本不像一段静态库代码，而是一个活的生产依赖——Google 的服务器能直接向应用进程下发数据，一条错误响应就能让进程挂掉。

这个区别比 issue 里报的 SDK 版本重要得多。团队一般把 analytics 当成旁观者——只是观察产品。但这次，旁观者亲手把产品拉下了线。我现在审每一个支持远程配置的非必要 SDK，只问一句话：你能不能让应用打不开？

## 服务器两小时，缓存再加四小时

官方时间线显示，事故始于 9 月 28 日 17:41（太平洋夏令时间）。Google 在 131 分钟后的 19:52 完成了修复的全量推送，整个过程无需 SDK 更新。但由于受影响的响应可能被缓存，Google 警告称部分应用实例可能还会继续崩溃最多四小时，直到 23:52（太平洋夏令时间）。

原始报告给出了最关键的线索：这不是普通的发布回归。四个受影响的版本同时开始崩溃。报告者检查了 42 次崩溃，每一次都发生在 SDK 从 `sdk-exp` 端点收到 HTTP 200 响应之后——应用随即在 Analytics 实验 worker 处理该响应时崩溃。Google 在置顶的解决方案中确认了原因：SDK 收到了一个格式错误的 payload。

Orosz 把影响范围描述为“所有使用该 SDK 的 iOS 应用和所有会话”。但我查阅的证据不足以支撑这个结论，所以不会把它当作确切数字来复述。不过公开的开发者报告确实显示多个团队遭遇了崩溃量的突然飙升。在一个 [iOSProgramming 讨论帖](https://www.reddit.com/r/iOSProgramming/comments/1wt0t3z/firebase_analytics_suddenly_causing_production/)里，开发者反映服务端修复后崩溃率下降了，但在缓存响应过期之前仍有残留。

## 已发布的二进制文件仍在变化

没有人远程改过那四个应用版本。行为变了，是因为代码里本来就有的逻辑接受了服务端下发的新数据。这让“固定依赖”和“托管依赖”之间那条常规界线变得不再可靠——包版本锁死了，但运行时行为没有全锁住。

这才是我在意的产品后果。一个团队可以审 SDK 更新、做测试、分阶段发布，但照样可能通过配置、实验、feature flag、模型或厂商返回的数据，在上线后悄悄引入新的故障路径。远程控制本来就是这类 SDK 的卖点，但一旦格式错误的输入能穿透子系统边界、把宿主应用搞崩，卖点就变成了风险。

> **Info:**
>
> 我的 SDK 审查规则：只要厂商能在应用发布后改变行为，这个集成就得按生产服务来对待，而不是一个普通依赖包。输入验证、故障隔离、监控，以及一个能在它卡住启动之前把它关掉的开关——一个都不能少。

我在 [Claude 服务事故](/news/claude-outage-dependency-test)后就说过类似的观点，但这次更严重。一个托管的编码工具挂了，顶多拖慢工作；一个移动分析 SDK 出问题，崩的是用户已经装在手里的应用。

## 熔断开关有用，前提是启动时能读到它

公开讨论里一个比较实用的建议是：把 analytics 初始化放在一个服务端控制的开关后面。方向我认同，但有一个前提——应用必须在走到高风险 SDK 路径之前就读到这个开关，而且这个开关不能依赖那个可能正在出问题的厂商。

Firebase 的 [iOS 文档](https://firebase.google.com/docs/analytics/ios/configure-data-collection)说 Analytics 数据收集默认开启。开发者可以在 `Info.plist` 里把 `FIREBASE_ANALYTICS_COLLECTION_ENABLED` 设为 `NO`，之后再通过 `setAnalyticsCollectionEnabled` 打开。Google 还提供了一个永久关闭的选项。这些开关确实存在，但这次事件说明你得实际测一下它们什么时候生效——不能想当然地认为一个运行时调用一定赶在自动初始化之前。

如果 analytics 不是渲染首屏所必需的，我会默认关掉它，等应用加载了自己托管的一份小策略文件之后再开。这个策略请求必须能安全地失败——超时、返回异常、控制服务不可用，都意味着 analytics 保持关闭，产品照常跑。

这种设计有代价：会丢掉早期会话事件，多一条要测的路径，归因也可能变复杂。但对遥测来说，我愿意付这个代价。丢几个事件，总比丢整个会话强。

## Google 修得很快，但契约还是破了

替 Firebase 说句公道话：Google 很快定位了服务端原因，两个多小时就推完了修复，也没逼着开发者赶一个 SDK 更新去挤 App Store 审核。大服务难免出一次部署事故，这次服务端修复就是客户最需要的恢复手段。

但修得快不代表问题不存在：为什么一个格式错误的实验 payload 能变成宿主应用里的致命异常？网络响应就是不可信输入，哪怕它来自 SDK 厂商自己的端点。客户端契约应该丢掉错误数据，在安全的前提下保留上一份已知正常的状态，记一条诊断日志，然后在没有 analytics 的情况下继续跑。一个非必要的子系统没有资格决定应用能不能启动。

沟通渠道也有问题。目前 [Firebase 状态仪表盘](https://status.firebase.google.com/)把 Google Analytics 的事故指向了一个单独的 Ads Status Dashboard，而这次事故的具体解释却出现在 GitHub issue 里。开发者确实找到了答案，但排查事故不应该靠追一条社交帖子追到仓库讨论区。

## 下一个 payload 来之前，我要做的事

我会盘点每一个在启动时拉取远程行为的 SDK，记下谁控制这个响应、初始化什么时候跑、应用怎么处理格式错误的数据。然后我会逼这些端点超时、返回空对象、返回错误类型、重放旧 payload。通过标准很简单：产品能正常打开，可选功能保持关闭。

我还会把 SDK 故障和应用发布分开监控。这次的关键线索就是四个老版本同时崩了。当崩溃量在没有新部署的情况下异动时，第一个排查视图就该包含远程配置、第三方响应和缓存状态。

Firebase 这次是从服务端解了围。应用团队能做的，基本就是等修复上线、等缓存过期。这才是我不能接受的地方。Analytics 可以帮我判断产品运行得好不好，但它不该有权决定产品能不能打开。
