Skip to content

desktop: runAction has no error handling — Export, Check for updates and MCP are silently inert when the engine is unreachable #4502

Description

@MervinPraison

Found by a six-lens audit of the desktop app on 27 Aug 2026. Every finding was reproduced against the code, not inferred.
Severity: low · audit rank 15 of 16.

Breaks: every branch is a bare await fetch(...), and b.onclick = () => runAction(def) (:1856) discards the promise. requireEngine is consulted only when the panel opens. Worst on Export (export_chats), the app's only backup path: the fetch rejects, navigator.clipboard.writeText is never reached, no toast appears, and the user pastes whatever was already on the clipboard into a file believing it is a backup.
Who / likelihood: any engine restart or crash with the Settings panel open — and the settings that restart the engine are in that same panel.
Where: ui/index.html:1870-1938. open_data_dir is the only branch that degrades correctly.

--- a/ui/index.html
+++ b/ui/index.html
@@ -1870,3 +1870,11 @@
 async function runAction(def){
   if(def.confirm && !await askConfirm(def.confirm.message,{ok:'Continue'})) return;
+  try{ await runActionInner(def); }
+  catch(e){ toast('That did not run: '+(e && e.message ? e.message : e)); }
+}
+// A failed export that says nothing is worse than no export: the user pastes
+// a stale clipboard into a file and believes they have a backup.
+async function runActionInner(def){
   if(def.action==='export'){

(the rest of the body unchanged, moved into runActionInner; the export branch additionally needs if(!r.ok) throw new Error(...) on each fetch, since a 500 does not reject).

Test — frontend/tests/engine-down.test.mjs (that file's exact subject): with the engine stub returning a network error, click Export and assert (a) navigator.clipboard.writeText was not called with stale content and (b) an error is visible. Today the click resolves into silence.



Not yet fixed. Filed so it is not lost with the session that found it. The fix and the test above are proposals from the audit — worth re-checking against current main before implementing, since the file has moved since.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaudeAuto-trigger Claude analysis

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions