改了一处折扣金额的展示逻辑,商品详情页不能加购了,结算页也无法支付。页面没有白屏,导航仍然正常,购买流程却走不下去了。我们在 React 电商演示应用 web-react-demo 中模拟了这次故障,用它来演示如何通过 RUM 排查前端问题。

两个页面报的都是同一个 toFixed 空值错误。查看 JS 堆栈,可以找到出错的折扣格式化函数;但要弄清这个函数为什么影响了两个页面,还需要看 React 组件堆栈。RUM SDK 会在捕获 React 渲染异常时,一并记录出错组件及其父组件。本例中,这份堆栈让我们找到了商品报价和订单汇总两个业务组件:它们都使用了同一个折扣展示组件,也因此受到了同一处缺陷的影响。
这篇文章记录了用 STAROps 排查这次故障的过程:查询受影响的页面,还原源码和组件堆栈,然后对比修复前后的加购、支付记录,确认用户能继续完成操作。后续版本则由 Mission 定期检查,持续观察错误和性能变化。文中的截图来自实际分析过程,也提供了免登入口,可以直接打开演示数据继续提问。
直接体验
点击下面的入口即可免登体验,查看演示应用最近 7 天的前端报错:
本文使用 2026 年 9 月 15 日 10:26—10:32(北京时间)的演示数据。进入后可在同一对话中继续追问;若样本已过期,需要换用有数据的时间范围。
一、演示应用与 React 异常采集
演示应用提供商品浏览、加购、结算和模拟支付,并接入 @arms/rum-browser-react。在初始化 RUM 后调用 initReactPlugin(ArmsRum),再用 SDK 提供的 ErrorBoundary 包住商品报价和订单汇总组件。
当这些组件渲染出错时,SDK 会把 error.stack 和 React 提供的 errorInfo.componentStack 一起上报:前者记录函数执行时的调用栈,后者记录出错组件及其父组件层级。两份堆栈随同一次异常保存,后面可以结合页面、版本和 SourceMap 分析。
下图中,结算页的报价区域已切换到降级界面,模拟支付无法继续,商店导航仍可使用。异常虽然被 ErrorBoundary 捕获,RUM 中仍保留了这次错误及其组件堆栈。

图 1:结算页的报价区域报错,无法继续模拟支付。
演示包含三个版本,分别呈现异常出现前、出现后和修复后的行为:
| 版本 | 作用 | 折扣字段缺失时的行为 |
| 1.0.0 | 正常基线 | 使用空值保护,操作可以继续 |
| 1.1.0 | 演示回归 | 调用 undefined.toFixed,报价组件报错 |
| 1.1.1 | 修复版本 | 恢复空值保护,操作可以继续 |
三个版本都已上传与运行 JS 匹配的 SourceMap。它将两类堆栈中的压缩文件行列位置映射回源码:既能找到实际抛错的语句,也能找到 React 业务组件的定义位置。
接入与上传步骤可参考 Web/H5 接入文档和 CMS2 CLI 符号表上传文档。
二、哪些页面受到影响
先在 STAROps 中询问这段时间的报错情况:
帮我看看 web-react-demo 在 2026 年 9 月 15 日 10:26 到 10:32(北京时间)为什么报错,影响了哪些页面?

图 2:报错集中在商品详情页和结算页。
STAROps 查到 5 次 TypeError,全部来自 1.1.0,错误信息均为 Cannot read properties of undefined (reading 'toFixed'):
- 商品详情页 /products/:productId:3 次。
- 结算页 /checkout:2 次。
三、报错对应哪一行代码
STAROps 根据异常堆栈中的 JS 文件和行列位置,查询对应的 SourceMap,定位到了 src/App.tsx 第 271 行:value!.toFixed(2)。它位于折扣格式化函数 formatDiscount 中。

图 3:报错定位到折扣格式化函数中的 value!.toFixed(2)。
export function formatDiscount(value?: number): string {
if (release.stage === 'regression') {
return value!.toFixed(2);
}
return (value ?? 0).toFixed(2);
}异常版本进入 regression 分支。当折扣字段缺失时,value 是 undefined,调用 toFixed 就会报错。这里的 ! 只是 TypeScript 非空断言,运行时不会替代码补上空值检查。
演示应用把缺失折扣视为无折扣。修复后使用 (value ?? 0).toFixed(2),先将缺失值替换为 0,再格式化显示。
四、用 React 组件堆栈还原业务路径
本例两个页面的 JS 错误堆栈相同:前两帧分别是 formatDiscount 和 DiscountAmount,其余帧来自 React 内部的渲染代码。它能定位到第 271 行的 toFixed,但其中没有商品报价组件 ProductOffer 或订单汇总组件 OrderSummary。
React 组件堆栈补充了出错组件在组件树中的位置。继续问 STAROps:
这两个页面各自经过哪些业务组件?请根据实际组件堆栈还原。
STAROps 读取 RUM SDK 采集的 React 组件堆栈,并使用对应构建的 SourceMap 还原压缩组件名。两个页面都出现了 DiscountAmount,它们的业务父组件却不同:

图 4a:商品详情页的 React 组件堆栈。SourceMap 将 Kh、Jh 还原为 DiscountAmount、ProductOffer,并保留 SDK ErrorBoundary 帧。

图 4b:结算页的 React 组件堆栈。同一个 DiscountAmount 的业务父组件变为 OrderSummary。
商品详情页的 Jh 对应 App.tsx:284 的 ProductOffer,结算页的 $h 对应 App.tsx:331 的 OrderSummary;两份组件堆栈中的 Kh 都对应 App.tsx:276 的 DiscountAmount。这些是组件定义的位置,实际抛错语句仍是第 271 行。
结合组件堆栈和源码,可以整理出下面的关系。组件层级按父组件到子组件排列,只保留关键业务组件:
| 页面 | React 组件层级 | 组件内的抛错位置 |
| 商品详情 | ProductOffer → DiscountAmount | formatDiscount,App.tsx:271 |
| 结算 | OrderSummary → DiscountAmount | formatDiscount,App.tsx:271 |
两条组件路径指向同一个 DiscountAmount,它渲染时调用的 formatDiscount 没有处理缺失的折扣值。因此,这次需要修复共享的格式化函数,并检查商品报价和订单汇总两个区域。JS 堆栈给出了修改哪一行,React 组件堆栈给出了哪些业务组件使用了这段代码。
五、1.1.1 发布后,报错是否恢复
上线一段时间后,直接追问
修复版本 1.1.1 上线并积累一段时间的访问数据后,可以回到同一对话中问:
web-react-demo 的 1.1.1 已经上线一段时间了。最近 1 小时,Cannot read properties of undefined (reading 'toFixed') 这个报错还出现吗?如果还有,是旧版本还是 1.1.1?商品详情页的加购和结算页的支付恢复了吗?
这次查询聚焦 1.1.1 的访问量、原报错是否仍然出现,以及加购成功的 cart_added、模拟支付成功的 order_paid 事件。如果旧版本仍有报错,也能按版本区分,避免把它算到修复版本上。
下面是本文演示数据中的版本对比结果:

图 5:演示样本中各版本的加购与模拟支付事件,商品和结算分别统计。
在本次已入库的折扣缺失样本中,1.1.0 的 3 个商品会话和 2 个结算会话均发生异常;1.1.1 对应的 3 个商品会话完成了加购,2 个结算会话完成了模拟支付,均未复现该异常。
用 Mission 持续观察后续发布
如果希望每次发布后都自动检查,可以在 STAROps 中创建一个长期任务,选择「RUM 发布观察」模板:
为 web-react-demo 创建一个长期的发布观察任务,每小时检查一次。自动发现新版本,对比它与此前稳定版本的 JS 错误、页面和接口性能,持续观察 24 小时,并把报告保存在任务中。
本例已创建 web-react-demo 发布观察 Mission(免登查看),每小时第 5 分钟运行。后续发布新版本时,可以打开同一个任务查看执行记录和观察报告。

图 6:web-react-demo 的发布观察计划,每小时检查一次,自动识别版本并对比错误和性能。
任务于 2026 年 9 月 15 日 12:05 自动触发,约 4 分 38 秒后完成并生成了首次观察报告(免登查看)。这次回看过去 24 小时,共识别 3 个版本、70 个会话,查询范围比前面的案例截图更大。
报告在 1.1.0 中查到 11 次 toFixed 错误,影响 10 个会话;1.1.1 没有出现这条错误,但 /api/orders 和 /api/quote 的 p90 延迟约为 1.4 秒。任务把这些接口列了出来,便于继续排查。

图 7:首次自动执行报告中的接口延迟对比,1.1.1 的订单与报价接口延迟偏高。
本次 1.1.1 只有 19 个会话,后续还需积累样本、继续观察。每轮执行记录和报告都会保存在同一个 Mission 中。
结语
这次排查中,JS 堆栈把错误定位到 formatDiscount,React 组件堆栈进一步指出它分别影响 ProductOffer 和 OrderSummary。RUM SDK 的 React 支持,让被错误边界捕获的渲染异常也能带着组件上下文进入分析。修复后,再查看加购、支付是否恢复,并用 Mission 持续观察后续版本的错误和性能。
可以打开 STAROps 免登演示,从文首的问题开始体验,再在同一对话里继续追问。




