1. 接口异常类 bug 为什么总在 Codex 手里“补丁化”列表页首屏请求失败页面只剩一张空表格没有重试入口也看不出到底是没数据还是接口挂了。这种场景你大概率遇到过。把这类问题丢给 Codex它最常见的反应是立刻在 catch 里补一句错误提示或者给表格加个空状态文案。动作很快但问题没解决——用户还是不知道发生了什么开发者也没搞清页面为什么退不回来。接口异常类 bug 的麻烦在于错误信息在到达 Codex 之前就已经散掉了。控制台可能有一条 network error请求封装可能把失败吞成了空数组页面层可能只用list.length 0判断空状态于是“请求失败”和“暂无数据”被混成同一个分支。Codex 拿到的是一个已经被压扁的现象它只能对着现象打补丁。我试过让 Codex 直接读代码找根因结果它经常在页面层打转改完提示文案接口一失败还是白屏。后来我换了个思路先让一个调试 Skill 把错误信息接住、结构化再交给 Codex 分析定位。Skill 负责“接住”Codex 负责“定位”分工明确之后修复路径才走得通。这篇就围绕 Codex 处理接口异常类 bug 的调试链路演示怎么用 Skill 先捕获并结构化错误信息再让 Codex 沿失败路径定位。你会看到可复制的 Skill 配置骨架、验证动作以及从异常捕获到修复的完整流程。适合正在用 Codex 做前端调试、又不想每次都靠猜补丁的开发者。2. TaoToken 前置给 Codex 和 Skill 准备可调用的模型入口Codex 本身是编辑器里的编码代理它要分析错误信息、生成调试计划背后得有一个稳定的模型调用入口。我这边用的是 TaoToken 的 API 来做模型对话和 Coding Plan把 Codex 的推理请求接到一个统一的地址上省得在多个 key 之间来回切。TaoToken 在这里的角色是模型调用层不是替代编辑器也不碰你的生产库。它提供 OpenAI 兼容的接口Codex 或你写的 Skill 脚本通过https://taotoken.net/api发请求拿回结构化的分析结果。官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content接入文档和 key 管理都在控制台里。你需要先拿到一个 API Key。进控制台创建 key然后把它写进环境变量别硬编码在脚本里。下面这条命令把 key 写进当前 shell 会话重启终端就失效适合本地调试export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你打算长期跑 Coding Plan 做 Agent 类任务建议把 key 放到.env文件里用dotenv加载避免每次开终端都手动 export。接入文档里有完整的参数说明包括模型名、超时、重试这些字段。注意API Key 只放在本地环境变量或密钥管理里不要提交到 Git 仓库也不要在前端代码里暴露。拿到 key 之后先做一次最小连通性验证确认 Codex 或你的 Skill 脚本能正常调用模型。这一步不做后面 Skill 接错误信息时会分不清是模型调用失败还是接口本身失败。3. 可复制配置Skill 先接住错误信息的骨架Skill 的核心职责是“接住错误信息并结构化”它不负责修复只负责把散落在控制台、请求封装、页面状态里的证据收集起来整理成 Codex 能直接读的格式。下面这个骨架你可以直接复制改掉项目相关的路径和字段名就能用。3.1 Skill 配置骨架{ name: systematic-debugging, version: 1.0.0, description: 接口异常类 bug 的启动阶段调试 Skill负责捕获并结构化错误信息, entry: skills/systematic-debugging/index.js, triggers: [接口失败, 首屏空白, 列表为空, 请求异常], inputs: { repro: { action: 打开列表页, condition: 接口返回错误、超时或网络不可用, result: 页面显示为空表格, expected: 页面应区分空数据和请求失败并给出恢复路径 }, errorCapture: { console: true, network: true, requestWrapper: true, pageLayer: true }, pageState: [list, loading, errorState, noData] }, outputs: [ 任务身份, 复现信息, 错误信息, 请求与响应检查计划, 页面状态检查计划, GitHub Skill 选择, 未覆盖项 ], constraints: { noCodeChange: true, noDirectErrorToast: true, singleRootCauseHypothesis: true } }这个骨架里几个字段值得说明。triggers是触发词Codex 在任务描述里命中这些词时Skill 才会启动。constraints.noCodeChange强制 Skill 在启动阶段不改代码noDirectErrorToast禁止它直接补错误提示singleRootCauseHypothesis要求它一次只提一个最可能的根因假设。3.2 错误捕获脚本Skill 的入口脚本负责把错误信息抓下来。下面这段是请求封装层的捕获逻辑用拦截器把失败响应和异常都记下来不让它被吞成空数组// skills/systematic-debugging/capture.js export function attachErrorCapture(axiosInstance) { axiosInstance.interceptors.response.use( (response) response, (error) { const captured { url: error.config?.url, method: error.config?.method, status: error.response?.status ?? null, statusText: error.response?.statusText ?? null, responseBody: error.response?.data ?? null, message: error.message, timestamp: Date.now(), type: error.response ? http_error : network_error }; // 写入全局捕获队列供 Skill 读取 window.__DEBUG_CAPTURE__ window.__DEBUG_CAPTURE__ || []; window.__DEBUG_CAPTURE__.push(captured); return Promise.reject(error); } ); }页面层的状态捕获单独写重点记录list、loading、errorState、noData四个字段在失败前后的变化// skills/systematic-debugging/pageState.js export function snapshotPageState(state) { return { listLength: state.list?.length ?? null, listCleared: state.list?.length 0, loading: state.loading, errorState: state.errorState ?? null, noData: state.noData ?? null, noDataRule: list.length 0, timestamp: Date.now() }; }3.3 交给 Codex 的启动模板Skill 把上面这些证据整理好之后按固定模板输出给 Codex。模板长这样## 任务身份 接口异常类 bug 调试启动阶段不修改代码。 ## 复现信息 - 动作打开列表页 - 条件接口返回错误、超时或网络不可用 - 结果页面显示为空表格 - 预期页面应区分空数据和请求失败并给出恢复路径 ## 错误信息 - 控制台异常从 __DEBUG_CAPTURE__ 读取 - 请求状态码和响应体从 __DEBUG_CAPTURE__ 读取 - 请求封装是否吞掉错误是/否附证据 - 页面层是否捕获失败结果是/否附证据 ## 请求与响应检查计划 1. 模拟接口 500观察请求封装返回值 2. 模拟超时观察 loading 是否关闭 3. 模拟登录失效观察是否跳转 ## 页面状态检查计划 1. 失败后 list 是否被清空 2. loading 是否关闭 3. errorState 是否存在 4. noData 是否只按 list.length 判断 ## GitHub Skill 选择 - 主 Skillsystematic-debugging - 后备 Skillwebapp-testing - 暂不采用test-driven-development根因未确定 - 排除web-artifacts-builder不涉及独立页面生成 ## 未覆盖项 - 能否模拟接口 500 - 能否模拟超时 - 能否验证登录失效这份模板的关键在于它把“错误信息”和“页面状态”拆成了两个独立检查计划。Codex 拿到之后不会一上来就改 catch而是先沿失败路径查证据。4. 验证请求从异常捕获到 Codex 定位的完整流程配置好之后跑一遍完整流程确认 Skill 能接住错误、Codex 能定位根因。4.1 启动 Skill 并触发异常先在本地起项目把attachErrorCapture挂到 axios 实例上然后在浏览器控制台手动触发一次失败请求// 在控制台执行模拟接口 500 fetch(/api/list?page1) .then((r) r.json()) .catch((e) console.error(captured:, e)); // 读取 Skill 捕获队列 console.table(window.__DEBUG_CAPTURE__);如果 Skill 配置正确window.__DEBUG_CAPTURE__里会出现一条记录包含url、status、responseBody、type字段。type是http_error还是network_error决定了后续排查方向。4.2 把结构化信息交给 Codex把 3.3 的模板填好连同捕获到的错误信息一起发给 Codex。注意模板里明确写了“不要修改代码不要直接补错误提示”。如果 Codex 的启动回复第一句就是“我会在 catch 中调用 message.error”让它重写。Codex 正确的启动回复应该先抓四类证据复现信息、错误信息、页面状态、未覆盖项。它应该沿失败路径走一遍页面发起列表请求 → 请求封装收到失败响应 → 失败结果传给页面 → 页面关闭 loading → 页面保留旧数据或设置错误状态 → 页面展示失败说明和重试入口 → 用户点击重试 → 请求成功后恢复列表这条路径里任何一步断了页面都会退化。请求层吞错页面不知道失败页面一失败就清空 list旧数据丢了loading 没关用户一直等失败状态和空状态混用用户以为没有数据。4.3 单一根因假设与最小验证Codex 走完路径后要求它给出一个最小验证。比如它可以说当前最可能根因是页面只用list.length区分空状态没有失败状态。证据来自接口失败后 list 被置空页面仍展示空表格。最小验证动作是模拟失败响应观察noData和errorState的变化。验证通过后再提修复方案。修复时把失败状态和空状态拆开noData只在请求成功且list.length 0时为 trueerrorState在请求失败时置位并保留旧数据或提供重试入口。4.4 修复后的三条路径验证修完不算完要同时验证三条路径避免把失败状态修好了又把真实空状态弄坏路径模拟条件预期结果首屏失败接口返回 500显示失败说明和重试入口不清空旧数据重试成功点击重试后接口返回 200列表恢复errorState 清除正常空数据接口返回 200 且 list 为空显示“暂无数据”不显示失败提示这三条路径都过了接口异常类 bug 才算真正收口。5. 本篇常见错排查5.1 Skill 没触发Codex 直接改代码检查任务描述里有没有命中triggers里的词。如果描述太笼统比如只写“页面坏了”Skill 可能不启动。把现象写具体比如“列表页首屏接口失败后页面显示为空表格”命中率会高很多。5.2 错误信息被请求封装吞掉window.__DEBUG_CAPTURE__是空的说明拦截器没挂上或者请求封装在拦截器之前就把错误转成了空数组。检查 axios 实例的创建顺序确保attachErrorCapture在业务请求之前执行。5.3 Codex 启动回复直接给修复方案模板里的constraints.noCodeChange和noDirectErrorToast没生效。检查 Skill 配置有没有正确加载或者把约束写进任务描述的第一段明确说“请先启动任务不要修改代码不要直接补错误提示”。5.4 noData 和 errorState 仍然混用根因假设没压到一个点上。让 Codex 重新走失败路径重点看noData的判断条件。如果代码里还是list.length 0就显示空状态说明失败状态没被单独建模。把noData改成requestSuccess list.length 0errorState单独置位。5.5 重试后旧数据没恢复页面在失败时清空了 list重试成功后没有重新赋值。检查重试逻辑里有没有重新发起请求并更新 list。如果用了缓存确认缓存没有被失败分支清掉。6. 继续用 TaoToken 跑通你的调试链路接口异常类 bug 只补提示远远不够。提示只是用户看到的结果根因可能在请求封装、错误传播、页面状态或退化路径上。让 Codex 先走调试 Skill把复现信息、错误信息、请求响应、页面状态和未覆盖项交出来根因没有压到一个假设前不改代码。如果你想把这条链路跑通先去控制台创建一个 API Key然后按接入文档把 Codex 或 Skill 脚本接到https://taotoken.net/api。验证模型调用是否正常可以用模型对话页面发一条测试请求确认返回结构符合预期。长期做编码和 Agent 类任务的话Coding Plan 更适合key 管理和额度都在控制台里。接入与排障API Keys 管理 接入文档验证模型连通性模型对话长期编码 / Agent 任务Coding Plan下一篇可以接着这条接口异常任务写收口。修完以后我会要求 Codex 同时验证首屏失败、重试成功和正常空数据避免把失败状态修好了又把真实空状态弄坏。