关于 sentry-javascript-bugs
面向 Sentry 前端代码审查的 JavaScript 缺陷模式技能,依据真实生产问题检查用户指定代码或当前分支差异。它会追踪相关数据流,并仅报告有具体触发路径的中高置信度问题。
主要功能
- 01检查空值访问与 API 响应处理
- 02审查仪表盘组件和 Trace 视图数据
- 03检查 React 生命周期与 AI 数据解析
- 04核查数组边界及逻辑正确性
- 05提供触发条件与具体代码修复
适用场景
- 01审查前端差异中的空值访问风险
- 02检查图表和 Trace 视图的异常数据处理
- 03排查异步操作与 React 生命周期问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ getsentry/ sentry --skill sentry-javascript-bugs安装后在 Claude Code 中输入/sentry-javascript-bugs确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdreferences/ai-insights-parsing.mdapi-response-handling.mddashboard-widget-errors.mdnull-reference-errors.mdrange-and-bounds-errors.mdreact-lifecycle-errors.mdtrace-view-errors.md详细介绍
Sentry JavaScript 前端缺陷模式审查
通过检查那些导致最多真实生产错误的模式,找出 Sentry 前端代码中的缺陷。
本技能编码了来自 428 个真实生产问题的模式(201 个已解决、130 个已忽略、97 个未解决),这些问题在 93,000+ 受影响用户中产生了超过 524,000 个错误事件。这些不是理论风险——它们是实际最常上线的缺陷,并附有来自已解决问题的已知修复方案。
范围
审查用户、Warden 或当前分支 diff 提供的代码。如果用户未提供目标,则审查当前分支 diff。从变更的 hunk 或文件开始,然后仅在需要确认行为时向外读取。
- 根据下方的模式检查项分析变更的代码。
- 在需要时,使用
Read和Grep追踪初始 diff 之外的数据流。跟踪组件 props、hook 返回值、API 响应结构和状态转换,直到确认行为。 - 仅报告 HIGH 和 MEDIUM 置信度的发现。
| 置信度 | 标准 | 操作 |
|---|---|---|
| HIGH | 已追踪代码路径,确认该模式匹配已知缺陷类别 | 报告并附修复方案 |
| MEDIUM | 存在该模式,但上下文可能减轻其影响 | 报告为需要验证 |
| LOW | 理论上的或在其他地方已被缓解 | 不报告 |
步骤 1:对代码进行分类
确定你正在审查的内容并加载相关参考。
| 代码类型 | 加载参考 |
|---|---|
| Null/undefined 属性访问、可选链、对象解构 | references/null-reference-errors.md |
| 仪表盘 widget、图表可视化、widget URL 生成 | references/dashboard-widget-errors.md |
| Trace 视图、span 详情、trace 树渲染 | references/trace-view-errors.md |
| API 调用、响应处理、错误状态、fetch 封装 | references/api-response-handling.md |
| React hooks、context provider、渲染循环、组件生命周期 | references/react-lifecycle-errors.md |
| AI Insights、大模型提示词解析、gen_ai span 数据 | references/ai-insights-parsing.md |
| 数组操作、日期/时间值、数字格式化 | references/range-and-bounds-errors.md |
如果代码跨越多个类别,请加载所有相关参考。
步骤 2:检查主要缺陷模式
这些按来自真实生产数据的频率和影响综合排序。
检查 1:Null/Undefined 属性访问——158 个问题,46,337 个事件
代码访问了可能为 null 或 undefined 的值上的属性。这是 Sentry 前端中最常见的单一缺陷模式。
危险信号:
- 在未进行 null 检查的情况下访问
.id、.slug、.name、.type、.match、.length、.charCodeAt - 对来自 API 响应的数据使用
object.property而非object?.property - 在未进行 null 验证的情况下将 API 响应数据直接传递给工具函数
- 在未检查元素是否存在的情况下从
querySelector或useRef访问 DOM 元素属性 - 解构来自可能在加载状态期间返回 null 的 hooks/store 的对象
- 对已卸载的元素调用
.dispatchEvent()
安全模式:
- 可选链:
obj?.property?.nested - 默认值:
const value = obj?.field ?? defaultValue - 函数调用前的 null 防护:
if (data) { parser.parse(data); } - 工具函数中对 null/undefined 参数的提前返回
检查 2:仪表盘小组件输入验证 -- 6 个问题,90,482 个事件
小组件可视化组件在接收到非预期格式的数据时会抛出异常。
危险信号:
- 渲染图表组件时未检查数据是否包含可绘制的值
- 对不支持多查询的小组件类型调用
getWidgetExploreUrl() - 将未定义的
field值传递给parseFunction()或类似的字段解析器 - 未处理小组件数据获取器中的空 API 响应
安全模式:
- 渲染前验证数据形状:
if (!hasPlottableValues(data)) return <EmptyState /> - 生成探索 URL 前检查小组件查询数量
- 守护字段解析器:
if (!field) return null
检查 3:Trace 视图数据完整性 -- 12 个问题,328,482 个事件
Trace 树渲染器和 Trace 详情视图会遇到违反结构假设的数据。
危险信号:
- 构建 Trace 树时未进行环检测(或检测到环但未优雅处理)
- 从 span 数据中按 ID 查找项目时未检查项目是否可访问
- 生成 Trace 链接时未验证
traceSlug非空 - 在渲染路径中使用
captureException时未去重(每个渲染周期都会触发)
安全模式:
- 通过将环节点分离为孤儿根节点来打破环
- 生成链接前验证 traceSlug:
if (!traceSlug) return fallbackLink - 使用 ref 对错误捕获去重:
if (!capturedRef.current) { captureException(...); capturedRef.current = true; } - 渲染 span 详情前检查项目访问权限
检查 4:API 响应形状假设 -- 31 个问题,24,019 个事件
前端代码假设 API 响应具有特定形状,但响应为空、未定义或具有非预期的状态码。
危险信号:
- 未处理 200 响应体为空的情况(例如
GET /customers/{orgSlug}/返回 200 但无响应体) - 未处理订阅流程中的 402(Payment Required)状态码
- 未处理变更端点中的 409(Conflict)状态码
- 将
UndefinedResponseBodyError视为非预期错误(它表示 API 未返回可解析的响应体) - 假设 SelectAsync 选项始终能成功加载
安全模式:
- 解析前检查响应体:
if (!response.body) return null - 在 catch 块中处理特定的 4xx 状态码
- 为失败的 API 获取提供回退空状态,而不是抛出异常
检查 5:React 生命周期违规 -- 10 个问题,2,595 个事件
组件违反 React 渲染规则,导致无限循环或崩溃。
危险信号:
- 在
useEffect中无条件设置状态,且未提供正确的依赖数组 - 在组织上下文加载之前渲染的组件中调用
useOrganization() - 在 Provider 边界之外使用
useContext() - 将对象作为 React 子元素传递,而不是字符串/元素
- 挂载时立即触发重新渲染的组件
安全模式:
- 始终为
useEffect提供依赖数组 - 守护上下文 Hook:
const org = useOrganization(); if (!org) return <Loading /> - 将依赖组织上下文的路由包裹在 Provider 边界中
- 渲染前验证元素类型:
if (typeof Component !== 'function') return null
检查 6:AI 洞察数据解析 -- 2 个问题,3,005 个事件
AI 提示词消息和 gen_ai span 数据的 JSON 解析在非标准格式下失败。
危险信号:
- 对
ai.prompt.messagesspan 属性调用JSON.parse()时未使用 try-catch - 假设所有 AI 模型响应都会产生有效的 JSON
- 未处理多模态 AI 消息的 “parts” 格式
安全模式:
- 将所有对外部数据的
JSON.parse调用包裹在 try-catch 中 - 解析前检查开头的
[或{ - 解析失败时提供原始文本回退渲染
检查 7:数组与边界校验 —— 15 个问题,3,120 个事件
数组操作以及数值格式化中使用了超出有效范围的值。
危险信号:
- 使用
result.push(...largeArray)(数组过大时会崩溃) - 向
toLocaleString({maximumFractionDigits: n})传入未做钳制的值 - 从未经验证的时间戳构造 Date 对象
- 递归渲染组件时没有深度限制
安全模式:
- 对可能很大的数组使用
concat或迭代 push - 钳制数值格式参数:
Math.min(100, Math.max(0, precision)) - 构造日期前先校验:
if (isNaN(new Date(ts).getTime())) return fallback - 对深层嵌套结构使用带显式栈的迭代渲染
检查 8:逻辑正确性 —— 不基于模式匹配
在检查完上述所有已知模式后,对改动过的代码本身进行推理:
- 每条代码路径是否都返回正确的类型(或 JSX)?
- 条件语句的所有分支是否都处理了(尤其是 switch 中缺失的
else/ 默认分支)? - 任何 prop 或 state 值(null、undefined、空数组、空字符串)是否会导致意外行为?
- hook 依赖数组是否正确?缺失依赖会导致闭包过期;多余依赖会导致无限循环。
- 如果此组件在异步操作中途卸载,是否处理了清理?
只有当你能够追踪到触发该 bug 的具体输入时才报告。不要报告理论上的担忧。
如果所有检查都没有产生潜在发现,就停止并报告零发现。不要为了填充报告而编造问题。当代码中没有匹配这些模式的 bug 时,空结果就是正确的输出。
每个代码位置应只在最具体匹配的模式下报告一次。不要在同一行上以多个检查重复标记。
步骤 3:报告发现
对于每个发现,提供审查框架所需的证据:
- 精确位置
- 严重程度与置信度
- 具体的触发输入或状态
- 根本原因与后果
- 如有可用的生产环境先例,提供匹配的先例
- 具体的代码修复,若框架支持,最好以统一 diff 形式提供
修复建议必须包含实际代码。绝不要建议以注释或 docstring 作为修复。
不要自行规定输出格式 —— 审查框架控制响应结构。