Repository navigation
desktop: "Images and files" picker never opens on Windows (Desktop IPC handler failed) #50153
Description
Activity
I reproduced the options.title decoding failure from the earlier comment against v2.0.11 using Effect 4.0.0-rc.112.
For this failure, the request is rejected before the file-picker handler runs, so it does not establish a failure in Electron's
showOpenDialogitself.The relevant path is:
renderer/platform/files.tsexplicitly includestitle: undefinedandextensions: undefinedwhen those options are absent.renderer/ipc-client.tsposts the payload directly over a MessagePort, without the Effect RPC client's schema encoding. Structured clone preserves these properties.main/ipc-transport.tsstill usescodecFor: Schema.toCodecJson. For the picker schema, an omitted optional field is accepted, but an explicitly presentundefinedis rejected.
Minimal reproduction, run from
packages/desktopat that tag:import assert from "node:assert/strict" import { Schema } from "effect" import { FilesOpenFilePicker } from "./src/shared/ipc-rpc/files" const decode = Schema.decodeUnknownSync(Schema.toCodecJson(FilesOpenFilePicker.payloadSchema)) assert.throws( () => decode({ options: { multiple: true, title: undefined, extensions: undefined } }), /Expected string \| null/, ) assert.deepEqual(decode({ options: { multiple: true } }), { options: { multiple: true } })
I also reproduced this through the actual
IpcServerProtocolLive,RpcServer, production RPC schemas and a MessageChannel with a raw renderer-style request. The failure is:Expected string | null at ["options"]["title"]A local candidate fix omits
undefinedobject properties recursively at the renderer's request boundary while preservingUint8Arrayvalues. It leaves server-side validation intact. Avoid JSON-stringifying the whole payload: attachment bytes must remain binary.Before normalization, five regression cases failed (file picker, absent options, directory picker, save dialog and
openPathwithout an application). With normalization, the focused suite passes 27 tests / 0 failures, including existing attachment size/authorization checks, multiple renderer ports and binary transfer:bun test src/main/ipc-transport.test.ts src/renderer/ipc-payload.test.ts src/renderer/platform/files.test.ts src/main/filesThe two
ipc-payloadfiles and additional transport cases are local additions, not present in the tag. Tests used Bun1.4.2and Effect/platform packages pinned to4.0.0-rc.112.Verification limit: this is a source/transport-level reproduction and candidate fix; full desktop typechecking/build and native-dialog end-to-end verification remain incomplete locally. I have not verified a rebuilt packaged app.
The current diff of #50207 improves error reporting but does not normalize request payloads, so it appears complementary to fixing this decoding failure.
I am using a tool to translate Japanese into English, so I apologize if the meaning is incorrect.Confirming this on Windows 10.0.26200 with Desktop 2.0.12 (Spanish UI).
I instrumented the desktop IPC error path in-place and the toast actually hides a chain of schema decode failures:
Expected string | null at ["options"]["title"]- After sending
title: nullinstead ofundefined:Expected array | null at ["options"]["extensions"] - After sending
nullfor bothtitleandextensionsinopenAttachmentPickerDialog, Ctrl+U works completely.
So the fix must normalize both optional fields (
titleandextensions) —openAttachmentPickerDialogsendstitle: t?.title, extensions: t?.extensions(bothundefinedwhen unset), while the request schema requires each field present asstring | null/array | null.Useful workarounds until fixed: paste images with Ctrl+V and drag & drop files. Everything else (Configuration file button, opening the config without an existing opencode.json, etc.) behaves as described in #50503.
Can confirm does not work
Fix PR: #50333
It addresses the
undefinedpayload decoding issue at the renderer IPC request boundary, including bothtitleandextensions, while preserving binary payloads.The fix has also been independently reproduced against the packaged Windows build, where applying the same normalization allowed Ctrl+U to open the native file picker.
Confirming repro on Desktop 2.0.13 (Windows 11 Pro 10.0.26200, x64) — the fix from #50599 (8e62ad7, merged today) is not in the shipped 2.0.13 build, so the
+menu → 图片和文件 ("Images and files") still fails with the toast请求失败 / Desktop IPC handler failed. The native dialog never opens, consistent with the same undefined-field rejection path.Extra details from my machine that may confirm the closed-loop:
- Timing: the toast appears immediately after choosing the menu entry, before any dialog (
showOpenDialog) appears. - Confirmed workarounds on 2.0.13: drag & drop into the composer works fine (no error, file attaches); paste from clipboard also untested in my case but drop is verified.
- Silent-diagnostics point (matches desktop: file/folder pickers always fail on Windows — request schema rejects
undefinedfor optionaloptions.title/options.extensions("Desktop IPC handler failed") #50503's instrumentation findings): nothing inmain.log,renderer.log, or Crashpad when the failure happens — theDieexit of the sharedUtrequest boundary is never logged, so the toast is the only signal. TheAppProtocolErrorbranch doesconsole.error('[desktop-ipc] protocol error', error), but a schemaFailat the renderer boundary never becomes one, which is why logging for failed desktop IPC requests would help future reports. app.getPath('documents')(onboarding) worked on this machine, unlike the secondary defect noted in desktop: file/folder pickers always fail on Windows — request schema rejectsundefinedfor optionaloptions.title/options.extensions("Desktop IPC handler failed") #50503.
Waiting for the next desktop release (> 2.0.13) that carries 8e62ad7; happy to verify the fix as soon as it ships.
- Timing: the toast appears immediately after choosing the menu entry, before any dialog (

Description
On OpenCode Desktop for Windows, choosing Images and files from the composer's
+menu never opens the native file picker. A toast appears instead:The native dialog never appears, so the main-process handler throws before it can show anything. The desktop IPC client only produces that message when the handler exits with a defect (unhandled throw) rather than a typed error:
The handler calls Electron's dialog directly, with no error mapping:
The renderer calls it with
{ defaultPath: <session directory>, multiple: true }.Plugins
None. No
opencode.json/opencode.jsoncin the project or in~/.config/opencode(onlyservice.json).OpenCode version
Desktop app
2.0.11(bundled CLI2.0.11). The updater reports 2.0.11 is the latest available, so this is not a stale build.Steps to reproduce
+button at the bottom-left of the prompt input.Ctrl+U).Reproduces consistently, including after a full reboot.
Screenshot and/or share link
No screenshots. The toast reads
请求失败/Desktop IPC handler failed, triggered from the图片和文件(Ctrl+U) entry of the composer's+menu.Operating System
Windows 11 Pro, 10.0.26200 (x64)
Terminal
N/A — desktop app (not the TUI)
Additional context
readClipboardImage,getPathForFile) work, so the IPC bridge itself is healthy — only theshowOpenDialogcall fails.Defectbranch of the IPC client rejects pending requests without logging, somain.log/renderer.logcontain no stack trace.throws inside the generator (desktop.picker.error.sizeLimit), so it appears to surface as the same generic message instead of its localized one.