Uh oh!
There was an error while loading. Please reload this page.
fix(app-shell): CloudConnectionPanel 绑定失败先读 error.message,与同文件 getJson 的优先级一致 - #5052
Conversation
….code on bind-poll failure
`poll()`'s terminal branch read `body?.error?.code ?? t('cloudConnection.errors.bindFailed')`,
so a failure body carrying a readable sentence beside its machine code was still
rendered as the code. This file's own `getJson` helper already reads
`message ?? code ?? error`; the one call site that diverged now matches it.
Narrower than issue #5028's premise, which verification moved: `/bind/poll`
serves the terminal device-authorization failure with HTTP 400 (both before and
after objectstack PR #9369), and `getJson` throws on any non-2xx whose body is
not `success: true` — so that text was always chosen by `getJson`, not by this
line. What the changed line governs is the 2xx path: the control plane's `/bind`
answer is forwarded verbatim with its own status, and a 200 that says
`success: false` reaches this branch.
Four cases pin the surface end to end, including a control that records where
the device-authorization text really comes from.
Co-authored-by: Claude <noreply@anthropic.com>yinlianghui
commented
Aug 17, 2026
正文已重写一次:首版里 Generated by Claude Code |
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
commented
Aug 17, 2026
PM 验收:ACCEPT(session 实物核验:merge-base 恰为批次基线 验收核心是采信这次前提归因修正(
四用例双向钉(2xx 带 message 优先、无 message 回落 code、全缺 i18n 兜底、400 路径控制组),两次变异均只红预判那一条。消费半径三文件 + console 目录 50 文件全绿,仓根 81/81。 派生物:#5054(服务端察觉的失败读英文、本地计时器察觉的同一失败读译文 —— 双语混杂 UX 题,附 A/B/C)已按 finding 入池待分诊,处置正确。顺带记账两条平台行为进案头:issues 端点会剥正文末尾 footer(PR/评论端点不剥,补法=另发评论);getJson 类先例复核时要连 HTTP 状态码路径一起读,不能只看行内表达式 —— 本次解锁评论的前提复验就差在这一步。 转 ready 并挂 auto-merge(squash)。 Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5028
poll()的终止分支原来读body?.error?.code ?? t('cloudConnection.errors.bindFailed'),所以即使失败信封里已经带着一句人能读的话,渲染出来的仍是机器码。同一文件上方的
getJson(:76)早就用message ?? code ?? error这条链;本 PR 只把唯一偏离的那个调用点拉回本文件已有的房规,不是新约定。
上游解锁引用
objectstack-ai/objectstack#9267 已于 2026-08-17 17:59:18Z 经 PR #9369(
d2e6b1d67)落 main:/bind/poll的失败信封现在带error.message(Device authorization failed: expired_token)与
error.declaredCode(RFC 8628 原拼写),data.pending: false刻意保留,轮询状态机不受影响。前提复验读数(基线
dc9d651a2c55c10a9e4d30434e429e5fdc5ae968)卡面钉的两处内容级读数,逐字复核,行号与卡面一致:
CloudConnectionPanel.tsx:128setPhase({ kind: 'error', message: body?.error?.code ?? t('cloudConnection.errors.bindFailed') });CloudConnectionPanel.tsx:76const msg = body?.error?.message ?? body?.error?.code ?? body?.error ??加上HTTP ${resp.status}模板串但卡面的「症状归因」不成立,这是本 PR 与卡面唯一的实质差异。 卡面预测上游落地后用户会看到
DEVICE_CODE_FAILED,即认为设备授权失败是由:128显示的。实测不是:/bind/poll以 HTTP 400 下发(packages/cloud-connection/src/cloud-connection-plugin.ts,PR #9369 之前是
pending ? 200 : 400,之后仍是400);getJson对任何「非 2xx 且 body 不是success: true」的响应先抛(:75),poll()的 catch(:130)渲染的是err.message;getJson那条已经正确的链选出。上游 message 一合并就到了 UI,本仓这一侧其实不欠这个。那么改动的这一行真正管什么:只有
getJson交还的 body(2xx)且既无data.pending又无
data.bound也无success: true才会落到这里。/bind/poll恰有一个这样的出口 —— 它把控制面/bind的应答连状态码一起原样转发(c.json(bindJson, bindResp.status))。控制面若以 200 回success: false(其侧的信封违规,正是 objectstack#9364 还在清点的那一类),就落在这一支,而这里过去显示的是码、不是它旁边那句话。
反向验证(方向先书面预判,commit 后变异,
git checkout --还原)四个用例,编号见测试文件。注意 PM 派单模板预判的是「新信封用例变红」,而实测新信封用例(① 控制组)
不可能因这一行变红 —— 它从不走这一行;能分辨优先级的只有同时带两半的 ② 号。如实记录:
codeENVIRONMENT_BIND_FAILED);①③④ 绿Tests 1 failed | 3 passed,失败即 ②,dump 里正是ENVIRONMENT_BIND_FAILEDcode ?? messageTests 1 failed | 3 passed,同一条、同一断言Test Files 2 passed / Tests 8 passed① 号在两次变异下都保持绿,就是「设备授权那句话不由这一行产生」的实测证据 —— 它作为控制组留在
文件里,好让下一个读者不必再去
poll()里找那段文案。验证
构建先行:
测试(仓根,经共享 verify 锁,
--maxWorkers=2):类型与门禁:
测试范围说明:app-shell 全量过重,按
packages/app-shell/src/console目录跑(含本次新增文件),另按消费半径把
packages/i18n的 cloudConnection 平价测试与 marketplace 的readApiError一并跑过 ——grep 全仓后,这三处是
cloud-connection相关的全部测试面。范围
只这一个调用点 + 一个测试文件 + 一个 changeset。卡面自留的 UX 题(是否一律偏好译文而非任何机器码)
不在本 PR 裁 —— 复验把它变成了一个更具体的 翻译 问题(线上那句话是英文,而面板对同一失败已有译文键
cloudConnection.errors.expired),已另立 finding 单记录(见下方评论),不夹带进本 PR。