Skip to content

fix(desktop): omit undefined fields from renderer IPC payloads - #50599

Merged
Hona merged 1 commit into
anomalyco:v2from
Hona:ipc-undefined-fields
Sep 22, 2026
Merged

Hona merged 1 commit into
anomalyco:v2from
Hona:ipc-undefined-fields

Conversation

@Hona

@Hona Hona commented Sep 22, 2026

Copy link
Copy Markdown
Member

Closes #50583, closes #50153, closes #50503, closes #50177, closes #50173, closes #50309

The composer's attach button, the folder picker, save dialogs and openPath all fail with Desktop IPC handler failed since 2.0.11. The native dialog never opens.

Why

#50112 made the renderer post RPC payloads over the MessagePort directly (structured clone, no RpcClient). The main process still decodes with Schema.toCodecJson, where Schema.optional(String) means key absent | string | null. Structured clone keeps a present-but-undefined key, so the request dies in schema decoding before the handler runs.

flowchart LR
  A["files.ts<br/>{ title: options?.title }<br/>→ title: undefined"] --> B["ipc-client.ts<br/>port.postMessage(raw)"]
  B --> C["ipc-transport.ts<br/>codecFor: toCodecJson"]
  C -- "Expected string | null<br/>at [&quot;options&quot;][&quot;title&quot;]" --> D["Cause.Die"]
  D --> E["toast: Desktop IPC handler failed<br/>(cause never shown)"]
  style D fill:#ff5c7a,color:#000
Loading

Before #50112, RpcClient encoded the payload through the same schema and dropped the undefined optionals on the way out. This restores that behaviour at the renderer boundary.

Change

  • omitUndefined drops undefined properties from a request payload the way JSON.stringify would, leaving Uint8Array payloads untouched.
  • ipc-client.ts runs every outgoing request payload through it.
// renderer → main, before
{ options: { multiple: true, title: undefined, defaultPath: "C:\\proj", extensions: undefined } }
// after
{ options: { multiple: true, defaultPath: "C:\\proj" } }

The transport test drives the real FilesOpenFilePicker schema through IpcServerProtocolLive with a raw renderer-style request and asserts both the rejection without normalisation and the success with it.

Affected requests

RPC undefined field Caller
FilesOpenFilePicker title, extensions attach button, Ctrl+U
FilesOpenDirectoryPicker title folder picker
FilesSaveFile title save/export
FilesOpenPath application open path without an app

Drag & drop and clipboard paste bypass these RPCs, which is why they kept working.

Since anomalyco#50112 the renderer posts RPC payloads over the MessagePort by structured clone, without RpcClient's schema encoding. The main process still decodes with the JSON codec, where an optional field is 'key absent | value | null'. A present key holding undefined, which is what the composer sends for the picker title and extensions, is rejected before the handler runs and surfaces to the user as 'Desktop IPC handler failed'.

Drop undefined properties at the renderer request boundary the way JSON.stringify would, leaving Uint8Array payloads untouched.

Closes anomalyco#50583, closes anomalyco#50153, closes anomalyco#50503, closes anomalyco#50177, closes anomalyco#50173, closes anomalyco#50309
@Hona
Hona requested a review from Brendonovich as a code owner September 22, 2026 10:39
Copilot AI lite review requested due to automatic review settings September 22, 2026 10:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

2 participants