Summary
If the AO daemon exits while the Electron app is open, the renderer detects Daemon stopped, but the current route keeps stale project/session UI mounted and interactive. There is also no visible in-app recovery action even though the Electron main process already exposes daemon:start over IPC.
This leaves users in a dead-end after a daemon crash: the sidebar empties, stale route actions remain enabled, and actions fail with AO daemon is not ready. Instead of guiding the user to restart/reconnect, the app requires an external/manual daemon restart or full app restart.
Repro
Tested on current main with isolated local state only.
- Start Electron with an isolated daemon:
AO_DATA_DIR=/tmp/reverbcode-qa-more/ao-data \
AO_RUN_FILE=/tmp/reverbcode-qa-more/running.json \
AO_PORT=31015 \
AO_TELEMETRY_EVENTS=off \
AO_TELEMETRY_METRICS=off \
AO_TELEMETRY_REMOTE=off \
VITE_AO_POSTHOG_HOST=http://127.0.0.1:9 \
npm --prefix frontend run dev
- Register a disposable git repo under
/tmp and open the project settings route.
- Kill the isolated daemon process while Electron stays open.
- Observe the sidebar/status and the still-mounted settings form.
- Click
Save changes.
- Restart a daemon on the same isolated state/port externally.
Expected
When the daemon exits, Electron should give the user a clear recovery path, for example:
- show a prominent
Restart daemon / Reconnect action wired to the existing daemon:start bridge, or
- disable stale route actions and show a route-level daemon-offline state until the daemon is ready again.
After the daemon recovers, stale AO daemon is not ready. route errors should clear or the route should refetch cleanly.
Actual
- The sidebar switches to
No projects yet and status shows Daemon stopped.
- The project settings route remains mounted with stale project data from before the crash.
Save changes stays enabled and fails with AO daemon is not ready.
- After a daemon is started externally and the status returns to
Daemon ready, the stale AO daemon is not ready. error remains visible on the settings route.
- No in-app restart/reconnect affordance is visible, despite the bridge already exposing daemon start.
Evidence
Screenshot: daemon stopped, sidebar empty, stale settings route still interactive:
/tmp/reverbcode-qa-more/evidence/daemon-crash-stale-settings-no-restart.png
Screenshot: daemon ready again, but stale route error remains visible:
/tmp/reverbcode-qa-more/evidence/daemon-crash-stale-settings-save-error.png
Daemon/API proof after crash:
/tmp/reverbcode-qa-more/logs/daemon-after-crash.txt
Dev log:
/tmp/reverbcode-qa-more/logs/electron-dev.log
Supporting log detail: after the daemon crash, Vite dev output repeatedly logged notification stream proxy errors against the default 127.0.0.1:3001, while this Electron run was using AO_PORT=31015.
Code Pointers
frontend/src/main.ts: daemon child exit sets status to stopped.
child.once("exit", ...) sets state: "stopped".
frontend/src/main.ts: the main process already registers ipcMain.handle("daemon:start", () => startDaemon()).
frontend/src/preload.ts: renderer bridge exposes daemon.start().
frontend/src/renderer/hooks/useDaemonStatus.ts: renderer observes daemon status/events but does not surface a restart action.
frontend/src/renderer/components/ProjectSettingsForm.tsx: stale settings mutation reports AO daemon is not ready. as a normal form error and does not clear it when daemon status later recovers.
Duplicate Check
I checked the current open issue/PR list. This looks new.
Nearby but not duplicate:
Contribution Value
This is a good focused frontend/Electron contribution:
- User-visible and flow-breaking after daemon crash or forced daemon shutdown.
- Reproducible locally without private credentials.
- The IPC capability already exists, so the fix can likely stay in the Electron renderer/topbar/shell status layer.
- A focused PR could add a daemon-offline recovery UI, wire it to
aoBridge.daemon.start(), disable stale destructive/form actions while offline, and clear/refetch stale route errors on recovery.
Summary
If the AO daemon exits while the Electron app is open, the renderer detects
Daemon stopped, but the current route keeps stale project/session UI mounted and interactive. There is also no visible in-app recovery action even though the Electron main process already exposesdaemon:startover IPC.This leaves users in a dead-end after a daemon crash: the sidebar empties, stale route actions remain enabled, and actions fail with
AO daemon is not ready.Instead of guiding the user to restart/reconnect, the app requires an external/manual daemon restart or full app restart.Repro
Tested on current
mainwith isolated local state only./tmpand open the project settings route.Save changes.Expected
When the daemon exits, Electron should give the user a clear recovery path, for example:
Restart daemon/Reconnectaction wired to the existingdaemon:startbridge, orAfter the daemon recovers, stale
AO daemon is not ready.route errors should clear or the route should refetch cleanly.Actual
No projects yetand status showsDaemon stopped.Save changesstays enabled and fails withAO daemon is not ready.Daemon ready, the staleAO daemon is not ready.error remains visible on the settings route.Evidence
Screenshot: daemon stopped, sidebar empty, stale settings route still interactive:
/tmp/reverbcode-qa-more/evidence/daemon-crash-stale-settings-no-restart.pngScreenshot: daemon ready again, but stale route error remains visible:
/tmp/reverbcode-qa-more/evidence/daemon-crash-stale-settings-save-error.pngDaemon/API proof after crash:
/tmp/reverbcode-qa-more/logs/daemon-after-crash.txtDev log:
/tmp/reverbcode-qa-more/logs/electron-dev.logSupporting log detail: after the daemon crash, Vite dev output repeatedly logged notification stream proxy errors against the default
127.0.0.1:3001, while this Electron run was usingAO_PORT=31015.Code Pointers
frontend/src/main.ts: daemon child exit sets status tostopped.child.once("exit", ...)setsstate: "stopped".frontend/src/main.ts: the main process already registersipcMain.handle("daemon:start", () => startDaemon()).frontend/src/preload.ts: renderer bridge exposesdaemon.start().frontend/src/renderer/hooks/useDaemonStatus.ts: renderer observes daemon status/events but does not surface a restart action.frontend/src/renderer/components/ProjectSettingsForm.tsx: stale settings mutation reportsAO daemon is not ready.as a normal form error and does not clear it when daemon status later recovers.Duplicate Check
I checked the current open issue/PR list. This looks new.
Nearby but not duplicate:
AO_ALLOWED_ORIGINSconfig breaking Electron CORS.Contribution Value
This is a good focused frontend/Electron contribution:
aoBridge.daemon.start(), disable stale destructive/form actions while offline, and clear/refetch stale route errors on recovery.