Skip to content

fix(desktop): return expected failures as codes across IPC - #4878

Draft
orangeCatDeveloper wants to merge 3 commits into
apache:mainfrom
orangeCatDeveloper:fix/ipc-expected-failure-envelope
Draft

fix(desktop): return expected failures as codes across IPC#4878
orangeCatDeveloper wants to merge 3 commits into
apache:mainfrom
orangeCatDeveloper:fix/ipc-expected-failure-envelope

Conversation

@orangeCatDeveloper

Copy link
Copy Markdown
Contributor

Summary

Stacked on #4457; review the last commit.

Changing a task's permission mode, plan mode, orchestration, or model while it is busy shows the generic "cannot change right now" toast in every locale, and an attachment that fails validation is reported by parsing an attachment_ingest:<code> token out of the error text.

Root cause: both Desktop serialization boundaries keep only Error.message. The Runtime Host already answers session.configuration.update with a structured code (session_busy, operation_conflict, …) and the Desktop client surfaces it as RuntimeHostOperationError.code, but the main-process IPC handler rethrows, so Electron hands the renderer Error invoking remote method 'sessions:setPermissionMode': Error: Session has a pending Interaction and the presenter can only fall back.

The fix moves expected failures into return values. The five session-setting handlers answer { ok: true, session } | { ok: false, code }, where code is the Host's own code narrowed to the four a user can act on; unexpected failures still throw. Attachment validation raises a typed AttachmentIngestBlockedError that preload and main turn into the submitMessage / send envelope's new attachment_blocked variant. On the renderer side the platform adapters unwrap a failed envelope into ExpectedOperationError(code), so the existing intent hook and sessionSettingFailureCopy keep their shape and map the code through a new updateFailures catalog. localizedShellErrorMessage no longer parses any token.

Boundaries: the protocol is untouched, so there is no Host version skew. The Runtime's session_control_blocked tokens stay for the CLI's local runtime, which is their only consumer. The plan-mode write in app-shell now goes through the session-settings port rather than window.maka directly, which is what keeps the root-file ratchet flat.

Refs #2672

Verification

apps/desktop typecheck (4 tsconfigs)        0 errors
renderer architecture check                  passed against 411512bd9 (app-shell tokens 15584 -> 15580, chat-actions 4086 -> 4080)
desktop main tests (dist)                    2164 pass / 6 fail (the 6 are browser-message-box + runtime-host-client-uds, red on the base commit too)
format:check / biome lint                    clean

Rendered-output assertions in expected-error-presentation.test.ts:

✔ session setting failures map expected update codes per locale
✔ unexpected setting failures keep the caller fallback

Before, a session_busy answer reached the toast as the locale fallback; after, sessionSettingFailureCopy('zh-CN', 'permission', new ExpectedOperationError('session_busy')).description renders 当前任务正在运行或有交互待处理,等结束后再改设置。 and the en catalog renders A task is running or waiting on you. Change this setting after it settles.

Not run: Electron e2e, packaged build.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code traced the failure path, wrote the envelope types, the main/preload/renderer changes, the catalog copy, and the tests; the design decision to keep the protocol untouched and the copy wording were reviewed by hand. The commit carries Generated-by: Claude Code.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@github-actions github-actions Bot added the effort/XL Under 2500 readable lines label Sep 5, 2026
@orangeCatDeveloper
orangeCatDeveloper force-pushed the fix/ipc-expected-failure-envelope branch 3 times, most recently from 705a9ac to 50629d3 Compare September 6, 2026 11:03
Raw exception text no longer reaches the UI: expected failures carry
machine-readable codes (with params where needed) that the renderer maps
through locale catalogs, and unexpected failures show a localized
fallback while redacted diagnostics go to the console. Plan controls and
work-board actions carry those codes across IPC in a structured envelope,
since Electron strips custom fields off thrown Errors.

Generated-by: Claude Code
@orangeCatDeveloper
orangeCatDeveloper force-pushed the fix/ipc-expected-failure-envelope branch from 13f4497 to 3af86a4 Compare September 6, 2026 21:12
Squash of the stacked increment, rebased onto fix/desktop-error-codes
(apache#4457) after its rewrite onto main: typed AttachmentIngestBlockedError
with the attachment_blocked envelope, ExpectedOperationError across the
preload and session-settings surface, typed session-configuration
transition errors in the Runtime, and the sessionSettingsActions
updateFailures catalog per locale. localizedShellErrorMessage no longer
parses any token.

Generated-by: Claude Code
Generated-by: OpenCode
@github-actions github-actions Bot added effort/XXL Over 2500 readable lines and removed effort/XL Under 2500 readable lines labels Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XXL Over 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant