Skip to content

[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

Closed

Description

@hotlong

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.

⚠️ Filed in this repo rather than in 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) return readApiError(payload, res).message.
  • ⇒ The code member 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:762 renders the menu when !localInstall && cloudInstall && !getRuntimeConfig().cloudUrl.
  • createCloudStack serves cloudUrl: '' with installLocal: false (cloud cloud-stack.ts:354-359), so conjuncts 1 and 3 hold on the control plane; the hidden case is the TENANT runtime.
  • cloudInstall is null on page load (no defaultEnvironmentId is sent, so getCloudInstallationInfo takes its empty-id early return) but is set by the post-install refresh at MarketplacePackagePage.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.

⚠️ Check 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

  1. changed the title [-][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[/+] on Sep 16, 2026
  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    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 transfer op, 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:blocked until then. ⛔ Do not dispatch it here.


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Migrated from objectstack-ai/objectstack#18397 — pm:blocked → pm:queue, lane domain:ui · 2026-09-25T00:58Z

    Acting 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.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 4 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-10432-reseed-purge-error-code
    Worktree: objectui-issue-10432
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/app-shell/src/console/marketplace/marketplaceApi.ts (reseedSampleData / purgeSampleData hand back the code that readApiError already reads, not only its .message), packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx (the Re-seed / Purge result handling: ENVIRONMENT_KERNEL_UNAVAILABLE renders as a terminal refusal with no retry offer), the i18n key(s) for that one sentence under packages/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 tier
    Clause-②: 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/. Live pm:dispatched claims of seats 1, 3 and 4, read at the same time, name no marketplace file. readApiError's other callers already destructure code (marketplaceApi.ts :203, :280, :687 on origin/main 0348bc9), so the card's "wider than two lines" worry does not hold: the two drops are at :571 and :592 (and :765 throws .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 of reseedSampleData / purgeSampleData is 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

  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    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

  6. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: objectui#10473 at 82f916e; ready + auto-merge in this act

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account.

    Implemented-by:  claude/issue-10432-reseed-purge-error-code
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the card's defect reseedSampleData / purgeSampleData now return { ok: false, error: message, code } from readApiError, which is unchanged. The code reaches the caller in both dialects readApiError reads, including HTTP 500 under the cloud#1145 sentence-withholding
    terminal refusal on ENVIRONMENT_KERNEL_UNAVAILABLE the 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 existing errorCodeIs helper does the match. Nothing re-enables the items while the page stays mounted
    every other code the else arms are byte-identical to the base. INTERNAL_ERROR keeps today's text and enabled items (control pins), and status handling is untouched
    the sentence new key marketplace.detail.sampleDataKernelUnavailable in 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 change
    Clause-②: no SampleDataActionResult is not reachable from @object-ui/app-shell's exports map (. + ./styles.css; the entry re-exports nothing from marketplaceApi). This was checked at head and in published 17.6.0
    tests 6 unit pins + 4 page pins. The dev reported 8 failing on the base (the two INTERNAL_ERROR controls pass by construction) and all 10 green on the head. The reviewer confirmed the pins would fail on the base by reading the code
    contract review PASS at CONTRACT_REVIEW_TIER on this head, record 5826661564 (the seat read the reviewer transcript: every turn at tier)
    semver '@object-ui/app-shell': patch, '@object-ui/i18n': patch (a locale key added under a fix is patch in 119 of 139 i18n changelog entries)
    governed NOT GOVERNED (15 paths)
    CI 43 check-runs on 82f916e: 40 success, 3 skipped by design, 0 red
    closing keywords the body's only closing reference is Fixes #10432

    Findings, each with its disposition

    • Reviewer nit: the PR body and changeset say the refusal lasts "the rest of the visit" and clears "on a reload". It clears whenever the route unmounts, so a param-only navigation keeps it, and leaving the page clears it. The prose is imprecise; the behaviour is right ⇒ Acceptance notes.
    • Out of scope, same file: uninstallLocal still throws readApiError(...).message and drops the code. It is not on this path, and no consumer branches on its code ⇒ Acceptance notes, not filed.
    • The PR assignee is not set. The dev's label-write was refused by its classifier. That is a seat matter, not a landing condition ⇒ reported to the maintainer.

    State

    ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable in this act.


    Generated by Claude Code

  7. added a commit that references this issue on Sep 28, 2026
    2a943bf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions