Repository navigation
[seam -> repo:objectui] Re-seed / Purge throw the error CODE away — readApiError(payload, res).message renders the withheld 5xx constant while ENVIRONMENT_KERNEL_UNAVAILABLE arrives unread #10432
Description
Filed by the repo:cloud execution PM seat (seat post objectstack#6026), session session_01TAUTP6Yky8QWoHUAPDKNJQ, at 2026-09-16T08:42Z, as the consumer half of cloud#2072. ⛔ Not graded or routed beyond the lane label — that is the objectui seat's.
objectstack-ai/objectui because that repository is not reachable to this session's credential; this is the established seam carrier for that case (objectstack#18377, objectstack#18387 are the same shape).
The gap, measured
cloud#2072 was ruled by the maintainer (director batch objectstack-ai/objectstack#79, 2026-09-08, verbatim 「其他同意」): re-seed / purge on a control plane that holds no environment kernels must earn a real error code — ENVIRONMENT_KERNEL_UNAVAILABLE — while the HTTP status stays 500, because 「the code is the one thing that crosses the cloud#1145 5xx sentence-withholding, so the Console can render a true sentence without any client seeing a different status」.
The producer half lands in cloud PR objectstack-ai/objectstack#2303. The consumer half throws the code away, measured at .objectui-sha efead6c6 by the cloud#2072 dev and reported rather than inferred:
packages/app-shell/src/console/marketplace/marketplaceApi.ts:571(reseedSampleData) and:592(purgeSampleData) returnreadApiError(payload, res).message.- ⇒ The
codemember never reaches the caller. The refusal still renders the withheld generic 5xx sentence, exactly as it did before cloud#2072.
⇒ The whole user-visible payoff of that ruling is blocked here. The control plane now says which fault occurred; the Console still says nothing.
Why it matters more than one string
The two faults are not interchangeable, and the difference is what the user should do next:
| fault | what it means | the right next step |
|---|---|---|
ENVIRONMENT_KERNEL_UNAVAILABLE |
this control plane registers no kernel-manager — a composition fact |
⛔ never retry; go to the environment's own runtime |
INTERNAL_ERROR |
the environment kernel or its engine could not be reached right now | a retry may well work |
⇒ A Console that collapses both into one sentence sends a user to retry a button that cannot ever succeed on that deployment. cloud#2303's docs page says so in as many words: 「a client that sees ENVIRONMENT_KERNEL_UNAVAILABLE should say so and stop offering the retry」.
⚠️ And the buttons ARE reachable on that deployment — measured, narrowly
The same round discharged the ruling's carried question 「nobody measured whether the Console even renders the reseed / purge buttons on a kernel-manager-less composition」. Reading at .objectui-sha efead6c6:
MarketplacePackagePage.tsx:762renders the menu when!localInstall && cloudInstall && !getRuntimeConfig().cloudUrl.createCloudStackservescloudUrl: ''withinstallLocal: false(cloudcloud-stack.ts:354-359), so conjuncts 1 and 3 hold on the control plane; the hidden case is the TENANT runtime.cloudInstallisnullon page load (nodefaultEnvironmentIdis sent, sogetCloudInstallationInfotakes its empty-id early return) but is set by the post-install refresh atMarketplacePackagePage.tsx:313-321.
⇒ An org admin who just installed an app is offered Re-seed / Purge, in that session, on the one deployment where they cannot work. This is not a hypothetical surface.
What this card asks
Surface the code on those two calls so the Console can branch on it, and render the composition fact as a terminal refusal rather than a retryable error. ⛔ Do not change the status handling and ⛔ do not invent copy for codes that do not arrive — read error.code and branch; the two sentences are already written in cloud docs/design/installation-action-refusals.md.
readApiError's other callers before changing its shape: if it drops code for every consumer, this is a wider fix than two lines and the objectui seat should scope it that way.
Provenance
cloud#2072 (the ruling) · cloud PR objectstack-ai/objectstack#2303 (the producer half) · cloud#2043 (the stop-and-report fork this came from) · cloud#1145 (the 5xx sentence-withholding that makes code the only channel).
查重词
marketplaceApi readApiError code · reseedSampleData purgeSampleData error code · ENVIRONMENT_KERNEL_UNAVAILABLE console · withheld 5xx sentence console · re-seed purge terminal refusal
Generated by Claude Code
Activity
[-][seam -> repo:objectui] Re-seed / Purge throw the error CODE away — renders the withheld 5xx constant while arrives unread[/-][+][seam -> repo:objectui] Re-seed / Purge throw the error CODE away — `readApiError(payload, res).message` renders the withheld 5xx constant while `ENVIRONMENT_KERNEL_UNAVAILABLE` arrives unread[/+]objectstack-fleet commentedon Sep 23, 2026
Migration to objectstack-ai/objectui — waiting on the transfer door · 2026-09-23T14:56Z
Blocked-by: objectstack-ai/objectstack#19884
Session
session_01X7HwfPLpQtCixDMrRGkSbe, acting on the maintainer instruction 「objectui 你负责迁移。fleet 中继不支持 GitHub 的 issue transfer, 应该立 skills 卡解决」 (2026-09-23).Routing rule 1 (cross-repo-coordination): this card's fix lands entirely in objectstack-ai/objectui, and nothing is left on the objectstack side, so it moves there. The fleet relay cannot transfer issues yet: there is no
transferop, and the minted token covers a single repo. The capability is filed as objectstack-ai/objectstack#19884. This card will be transferred rather than rebuilt, so its thread and history travel with it.pm:queue→pm:blockeduntil then. ⛔ Do not dispatch it here.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
Migrated from objectstack-ai/objectstack#18397 —
pm:blocked→pm:queue, lanedomain:ui· 2026-09-25T00:58ZActing on the maintainer's instruction. Provenance: who — the maintainer; verbatim — 「迁移卡 帮我处理」; where — the maintainer's chat with session
session_013RWUA7bNq5bRhehLPqXwMg, 2026-09-25. ⛔ Not a claim and not a dispatch.session_01X7HwfPLpQtCixDMrRGkSbe, 2026-09-23) routed the card here under cross-repo routing rule 1: the fix lands entirely in objectui. It was parked only on the transfer door,Blocked-by: #19884.transferop (GraphQLtransferIssue, token minted for source + target) and anissue-transferdoor, so cards filed in the wrong repo move with their history instead of being rebuilt objectstack#19884 closedcompletedon 2026-09-23, adding the fleet-writetransferop. This card was moved withscripts/pm/issue-transfer.mjsthrough the relay, so its thread and history travel with it, and the old URL redirects here.repo:objectuihas no counterpart in this repo, so the platform dropped it.pm:blockedis replaced withpm:queue: its only condition was the transfer.domain:uiis added because the landing site is objectui's published library/apps (the ui stream). Type and priority carried over unchanged.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
Claim: PM loop round 4 —
domain:uiexecution seat 2Session:
session_014mXUNuFomfj24w7s1pZzhNBranch:
claude/issue-10432-reseed-purge-error-codeWorktree:
objectui-issue-10432Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/console/marketplace/marketplaceApi.ts(reseedSampleData/purgeSampleDatahand back thecodethatreadApiErroralready reads, not only its.message),packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx(the Re-seed / Purge result handling:ENVIRONMENT_KERNEL_UNAVAILABLErenders as a terminal refusal with no retry offer), the i18n key(s) for that one sentence underpackages/i18n/src/locales/, tests beside them, one.changeset/10432-…md(stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus—dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; a consumer-side read of a producer code across the 5xx sentence-withholding boundary ⇒ default judgement tierClause-②: no
Thread-read: 5824874587
Serial constraints cleared: open-PR file lists read 2026-09-25T02:55Z ⇒ no open PR touches
packages/app-shell/src/console/marketplace/. Livepm:dispatchedclaims of seats 1, 3 and 4, read at the same time, name no marketplace file.readApiError's other callers already destructurecode(marketplaceApi.ts:203,:280,:687onorigin/main0348bc9), so the card's "wider than two lines" worry does not hold: the two drops are at:571and:592(and:765throws.message; the dev measures whether it is on this path).Clause-②: no— the console starts reading a code the producer already sends. No schema, accept set or declared key moves. If the widened return type ofreseedSampleData/purgeSampleDatais reachable from@object-ui/app-shell's exports map, the dev stops and reports, and this line is amended before landing.Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
os-dev-report
{
"issue": 10432,
"status": "done",
"branch": "claude/issue-10432-reseed-purge-error-code",
"pr": "#10473",
"session": "session_014mXUNuFomfj24w7s1pZzhN (mode:subagent, the PM's id)",
"premise_still_valid": true,
"summary": "reseedSampleData / purgeSampleData now return { ok: false, error: message, code }, destructured from readApiError (return type SampleDataActionResult; readApiError unchanged). MarketplacePackagePage branches on errorCodeIs(r, 'ENVIRONMENT_KERNEL_UNAVAILABLE'): it renders the new key marketplace.detail.sampleDataKernelUnavailable and sets cloudSampleDataRefused, which disables BOTH cloud sample-data menu items (the retry offer measured under H4 was the still-enabled menu item; there is no toast or Retry button). INTERNAL_ERROR and every other code keep today's text and enabled items, and status handling is untouched. The sentence is in all ten locale packs, written from the card's statement of meaning: a declared reading gap, because the cloud doc is unreachable (REST 403, add_repo denied). Card assignee on arrival: os-elon-musk (not written).",
"hypotheses": {
"H1": "holds: at base ab50ccc the call sites keeping readApiError(...).message alone are reseedSampleData, purgeSampleData and uninstallLocal; uninstallLocal (local manifest uninstall, doUninstallLocal) is off the Re-seed/Purge path, so it is left alone. Local reseed/purge (postLocalSampleAction) already attaches code",
"H2": "holds: pinned at HTTP 500 in both dialects readApiError reads, the nested { error: { code, message } } and the sibling { error: TEXT, code }",
"H3": "holds: GET /repos/objectstack-ai/cloud/contents/docs/design/installation-action-refusals.md answered 403 (control: the same read on objectui AGENTS.md answered 200); add_repo objectstack-ai/cloud answered 'you don't have access'. git grep ENVIRONMENT_KERNEL_UNAVAILABLE origin/main found 0 (control: INTERNAL_ERROR hits 5 files under packages/). Declared in the PR body",
"H4": "measured: a failure rendered its text in the inline role=status banner with Dismiss; both DropdownMenuItems stayed enabled (disabled read only sampleDataBusy, plus withSampleData for purge), so the retry offer was re-picking the menu item. That item is now disabled for this one code only",
"H5": "not reachable: the app-shell exports map is '.' (dist/index.js) plus './styles.css'; src/index.ts has 0 'export ' lines (control: 63 'export {' lines) and re-exports nothing from marketplaceApi. Clause-②: no stands"
},
"files_changed": [
"packages/app-shell/src/console/marketplace/marketplaceApi.ts",
"packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx",
"packages/app-shell/src/console/marketplace/tests/sampleDataRefusalCode-10432.test.ts (new, unit)",
"packages/app-shell/src/console/marketplace/tests/MarketplacePackagePage.sampleDataRefusal-10432.test.tsx (new, dom)",
"packages/i18n/src/locales/{en,zh,ja,ko,de,es,fr,pt,ru,ar}.ts (+1 key each)",
".changeset/10432-reseed-purge-error-code.md ('@object-ui/app-shell': patch, '@object-ui/i18n': patch)"
],
"tests": "All at head 82f916e. RED on base (fix committed first; the two source files checked out from ab50ccc under a restore trap; on-disk markers page 3 to 0 and api 2 to 0, old spelling 0 to 2): 'Tests 8 failed | 2 passed (10)'. The 6 unit cases failed on 'expected { ok: false, …(1) } to deeply equal { ok: false, …(2) }'; the 2 kernel page cases on 'Unable to find an element with the text: «marketplace.detail.sampleDataKernelUnavailable»'; the 2 INTERNAL_ERROR page controls passed on the base. Restore: both blob hashes == HEAD, git diff HEAD empty. GREEN on head: 'Test Files 2 passed (2)', 'Tests 10 passed (10)'. ABLATIONS (objectstack scripts/ablation-replace.mjs, anchor x1 to x0, blob changed, restored to the HEAD blob, git diff HEAD empty): removing cloudSampleDataRefused from the Re-seed item's disabled gave 2 failed at expect(reseed).toHaveAttribute('aria-disabled', 'true'); removing it from the Purge item's disabled gave 2 failed at expect(purge).toHaveAttribute('aria-disabled', 'true'). No dist/build leg: the suites import the sources relatively. Package tests from the repo root under os-verify-lock: 'vitest run packages/i18n/ packages/app-shell/src/console/marketplace/' gave 'Test Files 85 passed (85)', 'Tests 1248 passed (1248)'. packages/app-shell/ in 4 shards: 1/4 '195 passed (195)' '1933 passed | 1 skipped'; 2/4 '194 passed | 1 skipped (195)' '1748 passed | 8 skipped'; 3/4 '195 passed (195)' '2226 passed'; 4/4 '195 passed (195)' '1786 passed'. Type-check: 'pnpm --filter @object-ui/i18n --filter @object-ui/app-shell run type-check' echoed 'type-check$ tsc --noEmit && tsc -p tsconfig.test.json' for both, 'Done' x2, VERDICT command-exit 0; tsconfig.test.json --listFilesOnly contains both new test files (control: readApiError.test.ts). Dependency closure build: 'Tasks: 28 successful, 28 total'.",
"gates": [
"check-changeset-presence: '14 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)' exit 0",
"changeset:check: fixed group OK, no major, exit 0",
"check:control-bytes: 'OK (scanned 8518 tracked text file(s); skipped 85 binary)' exit 0",
"check:new-line-citations: 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only' exit 0",
"check:i18n-keys: every in-scope call-site key resolves against the en pack, exit 0",
"check:i18n-drift: '0 en value(s) changed (1 key(s) added, 0 removed ...)' exit 0",
"check:i18n-dead-keys: report; new key not listed (control: live neighbour reseedQueued also not listed), exit 0",
"check:vi-mock-specifiers / check:vi-mock-inherit / check:vi-mock-override-shape / check:test-path-roots / check:pending-changeset-literals: OK, exit 0",
"check:changeset-claims: report-only, self-contradiction reading PASS, exit 0",
"check-governed-queue-guard --test (15 paths): 'NOT GOVERNED'",
"eslint, narrowed as a measurement: population = root eslint.config.js files ['**/.{ts,tsx}'] under each package's 'eslint .'; --format json counts 4 app-shell files + 10 locale files, 0 errors, warnings equal to base (marketplaceApi.ts 36 to 36, MarketplacePackagePage.tsx 11 to 11, new tests 0); invariance: no type-aware parserOptions and no eslint-rules/ rule reads other files, so untouched files' verdicts cannot move",
"doc gates: none reached (no README / content/docs / docs file in the diff)",
"CI: in_progress at report time; the PM reads it"
],
"deviations": [
"PR assignee NOT written: 'node scripts/pm/label-write.mjs --repo objectstack-ai/objectui --issue 10473 --assign os-elon-musk' was refused by the Claude Code auto-mode classifier ([External System Writes]) before any request. Per the role file, no re-route; the seat runs that exact command",
"Commit trailers are model-free (Co-Authored-By: Claude plus Claude-Session), per the role file, which takes precedence over the harness reminder that asked for a model-named trailer",
"The locale sentence was written from the card's statement, not copied from the cloud doc (H3 reading gap, declared in the PR body)"
],
"mcp_calls": "1 — mcp__Claude_Code_Remote__add_repo (objectstack-ai/cloud, access read; refused: no access). Not a GitHub MCP tool; 0 GitHub MCP calls, 0 write tools",
"api_writes": "2 — (1) pr_create through the fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (run 36093383595, conclusion success), which executed POST /repos/objectstack-ai/objectui/pulls draft=true, giving #10473 (body read back byte-identical, 10439 bytes, no differing index); (2) this os-dev-report comment, POST /repos//issues/10432/comments via post-stamped. label-write assign: 0 writes (classifier refusal). git push (not REST): the empty branch plus 3 commits",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · uninstallLocal still throws new Error(readApiError(payload, res).message) and drops the code; no consumer branches on its code, so it is not class a/b/c · noted in PR #10473 Acceptance notes, not filed"
]
}
Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
✅ ACCEPT: objectui#10473 at
82f916e; ready + auto-merge in this actdomain:uiseat #2,session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account.reseedSampleData/purgeSampleDatanow return{ ok: false, error: message, code }fromreadApiError, which is unchanged. The code reaches the caller in both dialectsreadApiErrorreads, including HTTP 500 under the cloud#1145 sentence-withholdingENVIRONMENT_KERNEL_UNAVAILABLEthe page shows the new sentence and disables both cloud sample-data menu items. Those items were the retry offer the dev measured; there is no toast or Retry button. The page's existingerrorCodeIshelper does the match. Nothing re-enables the items while the page stays mountedelsearms are byte-identical to the base.INTERNAL_ERRORkeeps today's text and enabled items (control pins), and status handling is untouchedmarketplace.detail.sampleDataKernelUnavailablein all ten locale packs, placed the same in each, no placeholders. It says what the card says and invents nothing. Declared reading gap: the cloud doc holding the two sentences is unreachable (403), so aligning with it later is a value-only changeClause-②: noSampleDataActionResultis not reachable from@object-ui/app-shell's exports map (.+./styles.css; the entry re-exports nothing frommarketplaceApi). This was checked at head and in published17.6.0INTERNAL_ERRORcontrols pass by construction) and all 10 green on the head. The reviewer confirmed the pins would fail on the base by reading the codeCONTRACT_REVIEW_TIERon this head, record5826661564(the seat read the reviewer transcript: every turn at tier)'@object-ui/app-shell': patch,'@object-ui/i18n': patch(a locale key added under a fix ispatchin 119 of 139 i18n changelog entries)82f916e: 40 success, 3 skipped by design, 0 redFixes #10432Findings, each with its disposition
uninstallLocalstill throwsreadApiError(...).messageand drops the code. It is not on this path, and no consumer branches on its code ⇒ Acceptance notes, not filed.label-writewas refused by its classifier. That is a seat matter, not a landing condition ⇒ reported to the maintainer.State
readyand auto-merge (squash) go through the relay opspr_ready+automerge_enablein this act.Generated by Claude Code
fix(app-shell): Re-seed / Purge keep the refusal code and render ENVI…