Skip to content

500 error on POST /session/{id}/command when session.directory points to a moved/deleted project #35491

Description

@enihcam

Bug

POST /session/{id}/command returns HTTP 500 when the session's stored directory in the database points to a path that no longer exists (e.g. the project was moved or deleted after the session was created).

Steps to Reproduce

  1. Open a project at /path/to/old-location in the web UI
  2. Send a command message — works fine
  3. Move the project directory: mv /path/to/old-location /path/to/new-location
  4. Restart opencode (opencode web), open the web UI
  5. The old session appears in the session list
  6. Type a message and send → HTTP 500 returned
  7. noReply: true messages (e.g. /compact) succeed because they bypass the code path that validates the directory

Root Cause

The WorkspaceRoutingMiddleware extracts session?.directory from the session's database row and sets it as the routing directory. This directory is used by InstanceContextMiddleware to load the instance context, which initializes a FileSystem service rooted at that path. When the directory no longer exists, FileSystem.realPath() fails with ENOENT.

Because SystemPrompt.environment() (system.ts) has signature Effect<string[]> (no error type), the Fail from a missing directory is converted to a Die defect. This Die bypasses the handler's Effect.mapError(() => new HttpApiError.BadRequest({})) — which only catches Fail causes — and hits the default 500 error handler.

Error chain:

SessionHttpApi.command
  → SessionPrompt.command → prompt → loop → ensureRunning → runLoop
  → SystemPrompt.environment()
  → ctx.directory (from stale session row)
  → LocationServiceMap.get(ref) → FileSystem.realPath(stale directory) → ENOENT
  → Die defect → bypasses Effect.mapError(→BadRequest) → 500

Affected code

  • packages/opencode/src/session/system.tsSystemPrompt.environment() has no error channel, so any location boot failure becomes a Die
  • packages/opencode/src/project/project.tsfromDirectory() does not relink stale session directories when a project moves
  • packages/opencode/src/server/routes/instance/httpapi/handlers/session.tsrequireSession() does not validate that the stored directory still exists on disk

Related issues

Suggested fix approach

Three fixes that together cover all three related reports:

  1. system.ts: Wrap the location layer call with Effect.catchCause so ENOENT degrades to empty references instead of a Die defect
  2. project.ts: In fromDirectory(), auto-relink sessions under the same project_id whose directory no longer exists on disk
  3. handlers/session.ts: In requireSession(), check that the stored directory exists on disk and return 400 BadRequest if not

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

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