Skip to content

cli: projects whose directory was deleted are never removed from the recent projects list #54320

Closed as duplicate

Description

@renengade

Description

Summary

A project row is created the first time a directory is opened, and it is never removed — not even when the directory itself has been deleted and every session under the project has been deleted. Because each client also refreshes time_active while resolving locations, the dead project keeps jumping back to the top of the recent projects list (Ctrl+O) instead of aging out.

Environment

  • opencode version: v2.0.26
  • OS: Linux 6.6.114.1-microsoft-standard-WSL2 (WSL2), x86_64
  • Terminal: TERM=xterm-256color (TERM_PROGRAM unset)
  • Shell: /bin/bash
  • Install/channel: standalone binary at ~/.opencode/bin/opencode
  • Active plugins: none

Reproduction

  1. Open opencode in some directory and create a session there, e.g. cd ~/project/foo && opencode.
  2. Delete that directory from the filesystem: rm -rf ~/project/foo.
  3. Delete the session it created, either from the TUI (session.delete) or via the API:
    opencode api delete /api/session/<sessionID>. The session is gone — GET /api/session/<sessionID> now returns 404.
  4. List projects: opencode api get /api/project.

Expected Behavior

The project should disappear from the list: its directory no longer exists and it no longer owns any session.

Actual Behavior

The project row persists forever and is still returned by GET /api/project, so it keeps showing in the recent projects menu.

Worse, it does not merely persist — it stays near the top. Every time the client refreshes its locations it re-resolves each project, and for the dead project that resolution fails and still bumps time_active. The project in my DB had its last session on 2026-09-21, but its time_active is 2026-10-10 because I kept opening the recent-projects list.

Two further notes from digging around:

  • There is no supported way to remove or hide it. PATCH /api/project/{projectID} only accepts canonical, name, icon, and commands — there is no hidden/archived flag — and there is no DELETE /api/project. The project table likewise has no hidden/archived column.
  • The cascade only runs in one direction. session, session_v2, permission, project_directory, and worktree all declare ON DELETE CASCADE against project, but nothing ever deletes the project row, so orphaned projects accumulate.

After deleting the last session, the affected row in my database was a pure empty shell — session, session_v2, permission, project_directory, and worktree all matched 0 rows for that project_id — yet it still appeared in the list.

Additional Context

Corresponding log lines, repeating every few seconds while the recent-projects list is open, for a project whose directory no longer exists:

level=INFO  message="watcher subscribe" path=<parent-of-deleted-dir> type=entries ignores=0
level=INFO  message="watcher started"   path=<parent-of-deleted-dir> type=entries backend=node
level=INFO  message="watcher stopped"   path=<parent-of-deleted-dir> type=entries
level=INFO  message="Sent HTTP response" http.method=GET http.url=/api/location http.status=404

Schema of the project table as of this version:

CREATE TABLE `project` (
  `id` text PRIMARY KEY,
  `worktree` text NOT NULL,
  `vcs` text,
  `name` text,
  `icon_url` text,
  `icon_color` text,
  `time_created` integer NOT NULL,
  `time_updated` integer NOT NULL,
  `time_initialized` integer,
  `sandboxes` text NOT NULL,
  `commands` text,
  `icon_url_override` text,
  `time_active` integer DEFAULT 0 NOT NULL
)

Suggested fix, in order of preference:

  1. Garbage-collect projects whose canonical path no longer exists and that have no sessions, worktrees, or other dependent rows — either at startup or when listing projects.
  2. Failing that, add an explicit way to remove a project: DELETE /api/project/{projectID} and/or a "remove from recents" action in the recent-projects menu.
  3. At minimum, stop bumping time_active when location resolution fails with 404, so dead projects at least age out of the recent list on their own.

Current workaround: stop the background service and delete the row by hand:

opencode service stop
python3 -c "
import sqlite3
con = sqlite3.connect('<opencode.db>')
con.execute(\"DELETE FROM project WHERE id='<projectID>'\")
con.commit()
con.close()
"

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

  1. opencode-agent commented on Oct 10, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report and the digging into the schema and logs!

    I think this is a duplicate of #49442. That issue reports the same thing: projects whose directory was moved or deleted stay in the /open (Ctrl+O) list and can't be removed. The wider question of what should happen to deleted projects is being tracked in #39903.

    Possible duplicates and closely related issues, ordered by likelihood:

    Your finding that resolving a dead project keeps bumping time_active, so it never ages out of the recent list, is a useful extra detail. Please consider adding it as a comment on #49442 or #39903.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. opencode-agent commented on Oct 11, 2026

    @opencode-agent
    Contributor

    We haven't heard back, so I'm closing this as a duplicate of #49442, which reports the same problem: projects whose directory was deleted stay in the recent projects list (Ctrl+O) and can't be removed.

    To follow progress:

    Your finding that resolving a dead project keeps bumping time_active is still useful, so please add it as a comment on #49442 or #39903. If your problem turns out to be different, reply here and we can reopen.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions