Repository navigation
fix(data-objectstack): a ConnectionError nothing answered no longer carries an invented 503 - #29947
Merged
Merged
Conversation
…arries an invented 503 The ConnectionError constructor stamped `statusCode || 503`. connect()'s catch (a rejected discovery fetch) and the post-connect error state build it with no status, so answeredLoadFailure read the browser's "Failed to fetch" as the server's answer. The constructor now keeps statusCode undefined when none is passed; a discovery the server answered with an error status carries that status. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzfeRhCDTUFg4Reps3f
Contributor
Author
|
domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd 维护者速读(席位终稿)
席位核对 · ACCEPT · head
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Yibo Wang · project thread
Fixes #29916
Clause-②: no
Metadata-protocol: none
维护者速读
ConnectionError不再带一个编造的 503;服务器真正回答过的 503/504 照旧带状态码,发现接口被服务器以错误状态拒绝时带的是服务器的真实状态。createErrorFromResponse的同类问题,这是剩下的那个来源。statusCode由 503 变为未定义,错误类与 code 不变);仓内没有任何读取方按 503 分支;回滚即还原本 PR。ui/packages/data-objectstack/src/errors.ts(构造器去掉|| 503)、ui/packages/data-objectstack/src/index.ts(connect()的 catch 与发现接口!res.ok分支)、ui/packages/react/src/utils/error-message.adapter-connection-unanswered-29916.test.ts(真实适配器 + 共享读取规则的边界钉)。pnpm --dir ui exec vitest run packages/react/src/utils/error-message.adapter-connection-unanswered-29916.test.ts packages/data-objectstack/src/connectRetriesDiscovery-12318.test.ts,预期 9 个测试全部通过,其中断网用例读作network,已回答的 503 用例读作已回答。What changes
The
ConnectionErrorconstructor no longer invents a status. It stampedstatusCode || 503; it now passesstatusCodethrough, so an error built without one keepsstatusCodeundefined. Same shape as #29915 forcreateErrorFromResponse.I moved the default in the constructor, not at the two callers. The constructor's only status input is an optional number, so a caller could not say "no answer" to it. Every caller that omits a status is a no-answer path.
Every
new ConnectionError(caller, and what it carries now:index.tsconnect()catch, discoveryfetchrejectedindex.tsconnect()catch, discovery answered!res.okres.status)index.tsnoteServerUnanswered(post-connecterrorstate)errors.tscreateErrorFromResponsecase 503errors.tscreateErrorFromResponsecase 504Why the second row matters: the
connect()catch covers both a rejectedfetchand a discovery the server refused. Dropping the default alone would have flipped an answered discovery failure from "answered (wrong status)" to "unanswered". So the!res.okthrow now putsstatus: res.statuson its error, and the catch hands a numericstatusto the constructor. A discovery 401 now reads asunauthorized.Every data method opens with
await this.connect(). So a list or record read against an unreachable backend rejects with theconnect()error, andansweredLoadFailure/classifyLoadErrorread it. After this PR that read returnsnulland classifies asnetwork.Exported contract (the PM's mechanism assumption, measured):
ConnectionErrorandObjectStackError.statusCode?: numberare exported. The TypeScript type is unchanged, sincestatusCodewas already optional. The runtime value changes fornew ConnectionError(msg)with no status:503becomesundefined. Docs that describe it:ui/packages/data-objectstack/README.mdL582 calls it "Network/connection errors (503/504)". That still describes the answered 503/504 cases, but it does not say a no-answer error carries no status.content/docs/frontend/data-objectstack.mdxL497 shows "code 'CONNECTION_ERROR', statusCode 503" for agetObjectSchemafailure. That path only builds aConnectionErrorfrom an answered 503/504 (no-answer goes throughcreateErrorFromResponsetoUNKNOWN_ERRORsince fix(data-objectstack): a request that got no answer no longer reads as an answered 500 #29915), so it stays true.I left both docs as they are, because neither is in the claimed file surface. A wording follow-up for the README line is in the report.
Tests
ui/packages/react/src/utils/error-message.adapter-connection-unanswered-29916.test.ts. It sits next to fix(data-objectstack): a request that got no answer no longer reads as an answered 500 #29915's boundary pin, because the adapter cannot importansweredLoadFailure(react depends on data-objectstack). It drives the realObjectStackAdapterover a fakefetch:connect()over a rejectingfetch:ConnectionError,statusCodeundefined,answeredLoadFailurenull,classifyLoadErrornetwork.find()before connect with discovery unreachable: same.find()tripsnoteServerUnanswered: theerrorstate event'sConnectionErrorhas no status, null,network.createErrorFromResponse({ status: 503 })keeps 503 and reads as answered.unauthorized.connectRetriesDiscovery-12318.test.ts, "refused past the budget". It assertedstatusCode: 503on a discovery that was refused and never answered. It now assertsstatusCodeundefined.errors.test.ts: the bare-constructor pin moves from 503 to undefined. A new CONTROL checks that a passed 503 / 504 is kept.Acceptance notes
ui/packages/react/src/utils/, not in data-objectstack. This is fix(data-objectstack): a request that got no answer no longer reads as an answered 500 #29915's precedent, for the reason above. No other file outside the claim is touched.ui/branches on aConnectionError's 503. I greppedstatusCode === 503,status === 503andCONNECTION_ERRORoutside tests. The two 503 hits (metadata-admin/external/api.ts,preview/commitHistory.ts) read rawfetchresponses, not this class.Verification
All of it ran on head
7aaf1de9.pnpm --dir ui exec vitest run packages/data-objectstack/ packages/react/src/utils/(under the verify lock): VERDICT command-exit 0, 123 files and 1407 tests passed.Consumer sweep: all 60 test files outside data-objectstack that build a real
ObjectStackAdapter(app-shell, console and others, found withgrep -rl "new ObjectStackAdapter|createObjectStackAdapter"). VERDICT 0, 60 files and 487 tests passed.cd ui && pnpm exec turbo run build type-check --filter=@object-ui/data-objectstack --filter=@object-ui/react: VERDICT 0, 44/44 tasks.@object-ui/data-objectstack:type-checkand@object-ui/react:type-checkare both in the output.node scripts/check-sdui-manifest.mjs: exit 0, intact, 106 components.Ablation, on committed head
7aaf1de9withscripts/ablation-replace.mjs. Vitest aliases@object-ui/data-objectstacktosrc, so no dist rebuild was needed.statusCode || 503back in the constructor. 5 tests went red: the moved 12318 pin, theerrors.test.tsbare-constructor pin, and the three no-answer pins in the new file. The other 1402 stayed green, including every CONTROL. On restore, the blob was35dfadc2== HEAD andgit diff HEADwas empty.undefined). 2 tests went red: the answered-503 discovery CONTROL and the 401 pin. The other 4 stayed green. On restore, the blob was2098bca3== HEAD.Derived gates: dispatch-gates --commands, 36 at 7aaf1de, all exit 0; --ran: 36 derived, 36 run, 0 NOT-MEASURED
pnpm --dir ui exec vitest run scripts/: 170 files passed, 2 skipped (4979 tests).Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses. (CI runs it)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufzfeRhCDTUFg4Reps3f