Skip to content

Report an empty gateway answer in chopin status and name task rows without a stray space - #718

Merged
lavaman131 merged 2 commits into
mainfrom
status-empty-body-and-row-label
Oct 21, 2026
Merged

lavaman131 merged 2 commits into
mainfrom
status-empty-body-and-row-label

Conversation

@lavaman131

Copy link
Copy Markdown
Collaborator

Two small fixes. The connector changed, so the fix reaches users with the next chopin CLI release.

chopin status behind a gateway that answers with an empty body

A proxy answering for a Chopin that went away sends 502 with Content-Length: 0. Bun reads that empty body as JSON null over a real connection, so chopin status threw TypeError: null is not an object (evaluating 'body.error') instead of reporting the HTTP status.

jsonObject(response) in apps/connector/src/mcp.ts now reads every connector JSON answer and treats any body that is not a JSON object as empty. It is used by:

  • the machine check in status.ts (the reported bug), which now says "Chopin's answer was http-502"
  • post() in machine.ts, replacing the inline guard from Say why a run retries and keep its connection when the run ends #716
  • the version refusal() check
  • chopin update asking Chopin which release to install. For an empty answer it printed "null is not an object (evaluating 't.version')". It now prints "it recommends none" and installs the newest release, as before.

Build task row accessible name

A task row's button took its name from its content: the title, then a visually hidden , done. Chromium, and Playwright's name computation, separate that absolutely positioned hidden text from the title with a space. So every row read like "Connect the local agent on main , done, no change needed", whatever its title or state. That is why the existing e2e matched \s*,.

The button now has an explicit aria-label from taskRowName(inlineText(title), state, noChange):

  • inlineText (apps/web/src/chat/inline-text.ts) parses the title with the same mdast-util-from-markdown that react-markdown uses, so code, emphasis and links read as shown and raw HTML or images read as nothing. It lives in its own file so chat/markdown.tsx's reviewed design-contract hash is unchanged.
  • apps/web now depends directly on mdast-util-from-markdown and mdast-util-to-string, at the versions the lockfile already resolved through react-markdown. No new packages are installed.

Tests

  • status.test.ts: a real local Bun.serve answers 502 with an empty body. It failed with the TypeError before the fix and passes after.
  • update.test.ts: the compiled CLI against a Chopin that answers 200 with an empty body. It failed with the null message before the fix and passes after.
  • build-model.test.ts: the composed name for done, no change needed, blocked, in progress and queued, with titles ending in inline code or a link.
  • markdown.test.ts: inlineText matches the text InlineMarkdown renders.
  • implementation-launcher.e2e.ts: the title now ends in inline code, and the test asserts exact accessible names: Connect the local agent on main, done, no change needed and Review the connection, done. Before the fix it received … on main , done, no change needed.

Run locally: bun test (6715 pass), bun run types, bun run ci, the e2e for implementation-launcher, build-restart and machine-choice (59 passed), and docker build.

No screenshot: nothing visible changed, only the accessible name.

lavaman131 and others added 2 commits October 21, 2026 14:43
A proxy answering for a Chopin that went away sends 502 with Content-Length 0.
Bun reads that empty body as JSON null, so `chopin status` threw a TypeError
reading `error` of null instead of saying Chopin answered http-502. Every
connector read of a JSON answer now goes through one helper that treats a body
that is not a JSON object as empty: the machine check in status, registration
and pairing requests, the version refusal check, and `chopin update` asking
Chopin which release to install, which said "null is not an object" instead
of "it recommends none" for an empty answer.

Assistant-model: Claude Opus 5.5 (fast)
Assistant-workflow: inline (fast subagents)
Assistant-verification: regression tests failed before the fix and pass after it
Assistant-verification: bun test (connector suite and full suite) passed
Assistant-verification: bun run types and bun run ci passed
Co-authored-by: Alex Lavaee <alexlavaee@microsoft.com>
A task row's button took its accessible name from its content: the title and
a visually hidden ", done". Browsers set that absolutely positioned hidden text
apart from the title with a space, so every row read as "Deploy on main ,
done", whatever its title or state. The row now carries an explicit label
composed from the title's shown text, parsed as its inline Markdown renders,
and its state, with single spaces and nothing before the comma.

Assistant-model: Claude Opus 5.5 (fast)
Assistant-workflow: inline (fast subagents)
Assistant-verification: the browser test's exact name assertion failed before the fix and passes after it
Assistant-verification: bun test (web unit tests and full suite) passed
Assistant-verification: Build and machine browser tests passed
Assistant-verification: bun run types and bun run ci passed
Co-authored-by: Alex Lavaee <alexlavaee@microsoft.com>
@lavaman131 lavaman131 self-assigned this Oct 21, 2026
@lavaman131
lavaman131 merged commit 4a7f08e into main Oct 21, 2026
46 of 48 checks passed
@lavaman131
lavaman131 deleted the status-empty-body-and-row-label branch October 21, 2026 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant