Skip to content

Electron has no in-app recovery after daemon crash and leaves stale route actions enabled #394

Description

@areycruzer

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.

  1. 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
  1. Register a disposable git repo under /tmp and open the project settings route.
  2. Kill the isolated daemon process while Electron stays open.
  3. Observe the sidebar/status and the still-mounted settings form.
  4. Click Save changes.
  5. 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.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingfrontendElectron frontend laneneeds-triageMaintainer needs to evaluate this issuepriority: highFix soon

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions