Skip to content

Electron app shows empty board when daemon checkout path casing differs #414

Description

@anirudh5harma

Bug

The Electron app can render an empty board even when the daemon has projects and
sessions, if the daemon reports the same checkout path with different casing.

Observed locally on macOS:

daemon workingDirectory: /Users/anirudhsharma/documents/projects/reverbcode/backend
Electron expected cwd:  /Users/anirudhsharma/Documents/projects/ReverbCode/backend

Those paths resolve to the same directory on the local filesystem, but the app
treated them as different checkouts.

Analyzed against: a4e0458 | Confidence: High

Reproduction

On a macOS checkout where the daemon was started from a differently cased path:

cd frontend
nvm use 20
npm run dev

The daemon API still has data:

/tmp/ao project ls --json
/tmp/ao session ls --json

But the Electron renderer shows:

No projects yet.
Click + above to register a git repo.

Inspecting the live Electron renderer showed:

{
  "state": "error",
  "message": "Another AO daemon is already running from /Users/.../documents/projects/reverbcode/backend; expected this checkout at /Users/.../Documents/projects/ReverbCode/backend."
}

At the same time, direct renderer fetches to /api/v1/projects and
/api/v1/sessions returned the expected project and sessions.

Root Cause

frontend/src/main.ts compared daemon identity paths with string-normalized
path.resolve() values. That only lowercased paths on Windows.

macOS filesystems are often case-insensitive but case-preserving, so the same
directory can be observed as both documents/projects/reverbcode and
Documents/projects/ReverbCode. The daemon identity check then returned an
error status, and the renderer refused to trust the daemon API base URL.

Fix

Canonicalize path identity through realpathSync.native() before comparing
daemon checkout paths. Preserve the existing behavior of rejecting genuinely
different checkouts, and keep Windows comparisons case-insensitive.

The fix also handles non-existent child paths by canonicalizing the nearest
existing ancestor before applying the remaining path segments.

Impact

This can make the Electron app look empty or unable to use existing daemon data
even though the daemon is healthy and API calls return projects/sessions. It is
especially likely on macOS when a checkout or daemon was launched through paths
with different casing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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