Skip to content

desktop: missing or inaccessible project folder breaks project requests #50951

Open

Description

@OpeOginni

Description

When a saved project folder is missing, or when macOS blocks access to it, project requests to the local server fail with HTTP 500. Examples are GET /api/integration and GET /api/model. Desktop then can't load models or integrations, and nothing tells the user that the folder is the cause.

Windows: folder moved or deleted. Recreating the folder at its original path restores access. Example (fictional path, redacted from the supplied log):

PlatformError: NotFound: FileSystem.realPath (C:\Users\Test User\Projects\missing-project)
[cause]: ENOENT: no such file or directory, lstat 'C:\Users\Test User\Projects\missing-project'

macOS: access blocked by privacy settings. The error arrives as PlatformError: Unknown with an EPERM cause, not as a permission error. Server log (user path replaced with a fictional one):

timestamp=2026-09-23T16:25:52.826Z level=INFO run=7c7987d0 cause="PlatformError: Unknown: FileSystem.realPath (/Users/example/Documents)
    at Lf (/$bunfs/root/chunk-zr73h8af.js:2:721)
    at <anonymous> (/$bunfs/root/chunk-bh8xr96x.js:24:40210)
    at guarded (internal:shared:112:26)
    at processTicksAndRejections (native:7:39)
    at FileSystem.resolve (/$bunfs/root/chunk-m1pd9hsp.js:123:34410)
    at FileSystem.resolve (definition) (/$bunfs/root/chunk-fw24wvty.js:9:89799)
    at ConfigDiscovery.discover (/$bunfs/root/chunk-m1pd9hsp.js:123:41501)
    at ConfigDiscovery.discover (definition) (/$bunfs/root/chunk-m1pd9hsp.js:123:34024)
    at ServerProcess.start (/$bunfs/root/chunk-qq8x7a52.js:2:6440)
    at ServerProcess.start (definition) (/$bunfs/root/chunk-38hy4y2f.js:436:22432) {
  [cause]: Error: EPERM: operation not permitted, lstat '/Users/example/Documents'
}" http.span=72 role=server http.method=GET http.url=/api/model http.status=500

The macOS failure showed up in Desktop as a full-page ClientError: UnexpectedStatus (HTTP 500) error, and restarting didn't help.

Plugins

Unknown for the affected installations.

OpenCode version

v2.0.15

Steps to reproduce

Windows:

  1. Open a project in the desktop app.
  2. Close the app and move or delete the project directory.
  3. Reopen the app and select the saved project. Project requests fail and models are missing.

macOS:

  1. Open a project inside a privacy-protected folder, such as ~/Documents.
  2. Deny OpenCode access to that folder under System Settings > Privacy & Security > Files & Folders.
  3. Reopen the app. Project requests fail with HTTP 500.

Screenshot and/or share link

None for the Windows report. The macOS report showed the full-page HTTP 500 error screen.

Operating System

Windows (version not provided); macOS (version not provided).

Terminal

Desktop app (no terminal).

Activity

  1. changed the title [-]desktop: missing project folder breaks project requests[/-] [+]desktop: missing or inaccessible project folder breaks project requests[/+] on Sep 24, 2026
  2. haoyangzhang99 commented on Oct 3, 2026

    @haoyangzhang99

    Another data point on v2.0.22 (Desktop, macOS 27 / Darwin 27.0.0 arm64), which doesn't include #52668 yet.

    How the stale projects appeared: I ran opencode run --standalone (the 2.0.22 CLI bundled with Desktop) in four throwaway folders under OpenCode's own temp directory ($TMPDIR/opencode/<name>), then deleted the folders. All four stayed in the shared project list. GET /api/project on the Desktop service still lists them with the deleted path in sandboxes, even though those runs used a private server.

    Symptom: while no session was running, Desktop repeatedly showed "request failed" (HTTP 500) errors. The service log shows bursts of GET /api/mcp/resource and GET /api/mcp for three of the deleted folders, minutes apart (12 errors between 17:56 and 18:15 UTC):

    http.method=GET http.url=/api/mcp/resource http.status=500   (x2 per burst)
    http.method=GET http.url=/api/mcp http.status=500
    cause="FileSystem.DirectoryNotFoundError: Directory not found: $TMPDIR/opencode/limitcheck
      [cause]: PlatformError: NotFound: FileSystem.realPath ($TMPDIR/opencode/limitcheck)
        [cause]: Error: ENOENT: no such file or directory, lstat '$TMPDIR/opencode/limitcheck'"
    

    Direct reproduction: opencode api get /api/mcp --header 'x-opencode-directory:<deleted folder>' returns 500. The same request for an existing folder returns 200.

    Two things worth checking against #52668 and #50952:

    1. These were background requests for projects that weren't open. Even as 404s, they may still surface as error toasts unless Desktop handles LocationNotFoundError quietly outside session and draft tabs.
    2. Throwaway --standalone runs register permanent projects, and there's no supported way to remove a project. Cleanup currently means recreating the folder or editing opencode.db.

    Environment: OpenCode Desktop and service 2.0.22 (latest), zsh. Local plugins: two unrelated ones (system-prompt rewording and a status-bar bridge); neither calls MCP routes.

    Related: #50548, #49442.

  3. kaantokgozsec-hash commented on Oct 11, 2026

    @kaantokgozsec-hash

    Verified data point on Desktop 2.0.26 (Windows): the server side of #52668 works — Desktop still dead-ends silently

    Environment: Desktop 2.0.26 (bundled opencode-cli.exe 2.0.26, local daemon on 127.0.0.1:49374), Windows 11 10.0.26200, channel latest, no plugins configured. Username redacted below as <user>.

    What happened: a project folder was moved while it was open in Desktop (C:\Users\<user>\Desktop\shorts_pipeline → C:\Users\<user>\Desktop\distribution_coordinator\shorts_pipeline). After restart:

    • the model and agent pickers were absent from the composer;
    • sending anything showed "Select an agent and model — Choose an agent and model before sending a prompt.";
    • no banner or message mentioned the missing folder;
    • uninstall/reinstall did not help — the workspace/tab state persists under %APPDATA%\ai.opencode.desktop (drafts.sqlite plus persisted tab/session info), so the stale path survives reinstalls.

    Server behavior on 2.0.26 (the packaged daemon already includes #52668):

    > opencode-cli.exe api GET /api/model --header "x-opencode-directory:C:\Users\<user>\Desktop\shorts_pipeline"
    {"_tag":"LocationNotFoundError","location":{"directory":"C:\\Users\\<user>\\Desktop\\shorts_pipeline"},"message":"Location not found: ..."}
    HTTP 404 Not Found
    

    For an existing directory the same request returns 200 with the full model list. So the 500/PlatformError shape from the original 2.0.15 report is gone; the renderer just doesn't consume the structured error yet.

    Where the client drops it (from the served renderer bundle _assets/incompatible-server-panel-DTx7zmni.js, 2.0.26):

    • submit handler: let c=ai(e);if(!c){e.notify.missingSelection();return} — ai() returns nothing once model.selection.current() is null;
    • picker visibility: get modelControlsVisible(){return !e.model.model.loading} — with the model request failing, loading stays true, so the control is removed from the DOM instead of showing an error state.

    Workaround that restored full function (without moving files back):

    mklink /J "C:\Users\<user>\Desktop\shorts_pipeline" "C:\Users\<user>\Desktop\distribution_coordinator\shorts_pipeline"

    then opencode reload. GET /api/model returns 200 again and the composer recovers. Might be worth a docs/FAQ note for users on latest until #50952 ships.

    Happy to verify a staged build of #50952 against this exact setup (Windows 11, Desktop 2.0.26) if useful.

  4. digisus commented on Oct 12, 2026

    @digisus

    Reproduced on Linux (Debian 13, desktop 2.0.16, bundled CLI 2.0.16) after a project folder was moved from ~/Documents/CODING to ~/Coding. Same PlatformError: NotFound: FileSystem.realPath 500s, plus two aspects not covered above:

    1. It is fatal, not degrading. The renderer dies with ClientError: UnexpectedStatus: 500 on every launch and the app is stuck on the error screen — no way to switch projects or dismiss it from the UI. Recovery required stopping the app and repairing state manually.

    2. Sessions stranded in a missing directory are polled in an unbounded retry loop. From the server log while the folder was missing:

    count endpoint
    349 /api/session/<id>/permission
    92 /api/session/<id>/form
    45 /api/location
    22 /api/provider · /api/model

    The session polls had no backoff and never gave up. Sessions whose directory is gone keep 500ing forever — GET /api/session/<id>/permission still returns 500 for them, and there is no API to re-home a session (only PATCH /api/project/{id} {"canonical": ...} exists for projects; I used it successfully, plus direct DB edits for the 4 stranded sessions).

    Suggestions:

    • server: return a structured 4xx (e.g. 404 + JSON error) for missing directories instead of 500
    • desktop: render the shell anyway; show stale projects/sessions as "folder not found" with a re-link prompt instead of a fatal error screen
    • desktop: bound/back off the session polling
    • desktop: a "project folder moved → locate new folder" flow
  5. neriousy commented on Oct 23, 2026

    @neriousy
    Member

    Preserving the Desktop fatal-rename details from #49442: on Desktop 2.0.22/Linux, renaming a stale project entry led to a repeatable HTTP 500 startup lockout; removing that entry from drafts.sqlite restored startup. A related report says failed location resolution still bumps time_active, keeping dead projects at the top of the recent-project list.

  6. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report. I reproduced both cases with the local server, without Desktop.

    I ran opencode serve (v2.0.15), opened a few project folders, then deleted one and made another unreadable (chmod 000 on Linux, which is close to macOS blocking a folder). After restarting the server, GET /api/model and GET /api/integration returned HTTP 500 with an empty body for both folders. The script below reproduces it.

    On the latest dev (fa1260d):

    • Missing folder (your Windows case): now returns a 404 LocationNotFoundError instead of 500. Desktop has a "location missing" prompt for this case, so that part looks fixed for the next release.
    • Folder that can't be accessed (your macOS case): still returns HTTP 500 with no message. The server knows the cause (DirectoryAccessDeniedError: Access denied to directory), but it doesn't pass that on to the app, so the app can't tell you the folder is blocked. This matches the full-page UnexpectedStatus error you saw.

    Until this is fixed, you can work around the macOS case by allowing OpenCode access under System Settings > Privacy & Security > Files & Folders, or by moving the project out of the protected folder. I've passed this to the maintainers.

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Reproduces #50951: project requests return HTTP 500 when the project folder
    # is missing or unreadable. Run as a NON-root user so chmod 000 takes effect.
    # Usage: OPENCODE="opencode" ./repro.sh   (or OPENCODE="bun ... packages/cli/src/index.ts")
    set -u
    OPENCODE=${OPENCODE:-opencode}
    export OPENCODE_PASSWORD=repro
    PORT=${PORT:-4999}
    W=$(mktemp -d /tmp/oc50951.XXXX)
    export HOME=$W/home XDG_CONFIG_HOME=$W/home/.config XDG_DATA_HOME=$W/home/.local/share XDG_STATE_HOME=$W/home/.local/state XDG_CACHE_HOME=$W/home/.cache
    mkdir -p "$HOME" "$W/ok" "$W/missing" "$W/denied"
    cd "$W"
    $OPENCODE serve --hostname 127.0.0.1 --port $PORT >"$W/server.log" 2>&1 &
    PID=$!
    for i in $(seq 1 60); do curl -s -u opencode:repro -o /dev/null "http://127.0.0.1:$PORT/api/model" && break; sleep 1; done
    
    req() { # $1 label, $2 dir, $3 path
      local code body
      body=$(curl -s -u opencode:repro -w '\n%{http_code}' -H "x-opencode-directory: $2" "http://127.0.0.1:$PORT$3")
      code=${body##*$'\n'}; body=${body%$'\n'*}
      echo "[$1] GET $3 -> $code  ${body:0:300}"
    }
    
    # Warm up all three locations while they exist (simulates a saved project)
    for d in ok missing denied; do req "$d (exists)" "$W/$d" /api/model; done
    
    # Now break them
    rm -rf "$W/missing"
    chmod 000 "$W/denied"
    for p in /api/model /api/integration; do
      req ok "$W/ok" $p
      req missing "$W/missing" $p
      req denied "$W/denied" $p
    done
    
    # Restart server (like reopening the app) and query again
    kill $PID; wait $PID 2>/dev/null
    $OPENCODE serve --hostname 127.0.0.1 --port $PORT >>"$W/server.log" 2>&1 &
    PID=$!
    for i in $(seq 1 60); do curl -s -u opencode:repro -o /dev/null "http://127.0.0.1:$PORT/api/model" && break; sleep 1; done
    echo "--- after restart ---"
    for p in /api/model /api/integration; do
      req missing "$W/missing" $p
      req denied "$W/denied" $p
    done
    kill $PID; chmod 755 "$W/denied"
    echo "--- server log (errors) ---"
    grep -iE "status=5|PlatformError|EACCES|ENOENT" "$W/server.log" | head -8 | cut -c1-400

    Run it: bash repro.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions