Skip to content

A folder that no longer exists gets turned into a new project #57988

Closed

Description

@lambert-zhh

Description

A folder that no longer exists gets turned into a new project. In my case it was the folder of a deleted workspace (see the related report about deleting such workspaces). It was still in the app's "recently closed" list, and after an app restart the service created a new non-git project for it.

Environment

  • OpenCode Desktop 2.1.2 (arm64), macOS 27.0.1

What I saw

  • The app restarted at 19:39:16. At 19:39:19 a new project row appeared for <parent>/.worktrees/<name> (the deleted folder), with vcs = null and no sessions.
  • At the same time the service answered GET /api/vcs/status and GET /api/vcs/diff with 404 several times, and started watchers on the parent folders.
  • The project shows up in GET /api/project. Its time_active was updated again at the next launch.
  • The path was still in the app state: drafts.sqlite, row opencode.global.dat / server, recentlyClosed.local.

Expected

No project is created for a directory that doesn't exist. Missing paths in "recently closed" are dropped or shown as missing.

Actual

A project for a missing folder is created and kept.

Activity

  1. opencode-agent commented on Oct 22, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report. I reproduced this with the server API on 2.1.2, and it still happens on the latest dev (248bfbe).

    What I did (the script is below):

    1. Started opencode serve with a fresh data directory.
    2. Sent GET /api/vcs/status and GET /api/vcs/diff for a .worktrees/<name> folder that doesn't exist. Both correctly return 404 LocationNotFoundError.
    3. Checked GET /api/project: it now lists a project for that missing folder (no vcs, no sessions).
    4. Restarted the server: the project is still listed.

    So the 404 is right, but the service saves the project before it notices the folder is missing, and it keeps it afterwards. That fits what you saw after the app restarted with the deleted workspace still in "recently closed". I only tested the server side; I didn't check the Desktop "recently closed" handling.

    Related issues:

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Repro for #57988: a request for a directory that doesn't exist creates a persisted project row.
    # Usage: ./repro.sh            (uses `opencode` from PATH)
    #        OC_DEV=/workspace/repo ./repro.sh   (runs from a source checkout)
    set -u
    PORT=${PORT:-$((20000 + RANDOM % 20000))}
    export OPENCODE_PASSWORD=repro
    C="curl -s -u opencode:repro"
    ROOT=$(mktemp -d /tmp/opencode/repro57988.XXXX)
    export HOME=$ROOT/home XDG_DATA_HOME=$ROOT/data XDG_CONFIG_HOME=$ROOT/config XDG_STATE_HOME=$ROOT/state XDG_CACHE_HOME=$ROOT/cache
    mkdir -p "$HOME" "$ROOT/cwd"
    MISSING=$ROOT/parent/.worktrees/deleted-ws   # never created
    run() {
      if [ -n "${OC_DEV:-}" ]; then
        bun --conditions=browser --preload="$OC_DEV/packages/tui/node_modules/@opentui/solid/scripts/preload.js" "$OC_DEV/packages/cli/src/index.ts" "$@"
      else opencode "$@"; fi
    }
    start() { (cd "$ROOT/cwd" && run serve --port $PORT >"$ROOT/serve.log" 2>&1) & PID=$!
      for i in $(seq 60); do $C -o /dev/null http://127.0.0.1:$PORT/api/project && return; sleep 1; done; echo "server did not start"; cat "$ROOT/serve.log"; exit 1; }
    stop() { kill $PID 2>/dev/null; pkill -P $PID 2>/dev/null; wait $PID 2>/dev/null; sleep 1; }
    enc=$(python3 -c 'import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))' "$MISSING")
    
    start
    echo "== projects before"; $C http://127.0.0.1:$PORT/api/project; echo
    echo "== missing dir exists? $( [ -e "$MISSING" ] && echo yes || echo no )"
    for ep in vcs/status vcs/diff; do
      echo "== GET /api/$ep for missing dir:"; $C -w ' [HTTP %{http_code}]' "http://127.0.0.1:$PORT/api/$ep?location%5Bdirectory%5D=$enc"; echo
    done
    echo "== projects after"; $C http://127.0.0.1:$PORT/api/project; echo
    stop
    echo "== restart server; projects after restart"
    start; $C http://127.0.0.1:$PORT/api/project; echo; stop

    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