Repository navigation
Open
Labels
Description
Summary
When a tool execution that triggered a permission prompt is interrupted (run aborted / exception / wait timeout), the permission dialog stays pinned above the composer in the OpenCode Desktop UI. The composer becomes unusable (new input cannot be typed), and clicking Deny / Allow once / Always allow only fires a reply request that the server answers with HTTP 404 — the dialog never goes away.
Environment
- opencode version: 2.0.29 (desktop app embedded server,
opencode serve --service, channel: latest) - OS: Windows_NT 10.0.26300 (win32 x64)
- Terminal: OpenCode Desktop (Electron) UI
- Shell: Windows PowerShell 5.1 (server-side tool shell)
- Install/channel: latest (desktop)
- Active plugins: none configured
Reproduction
- Have an
editpermission rule witheffect: ask(e.g.{ "action": "edit", "resource": "D:/Dev/Code/**", "effect": "ask" }). - In Desktop, run an agent task that triggers a write/edit under that rule → the "Needs permission" dialog appears above the composer (buttons: Deny / Always allow / Allow once).
- While the prompt is pending, the tool execution gets interrupted — observed when the run was aborted and the pending tool call shows "Tool execution interrupted". (Per user report it also happens when the permission request itself errors or waits until timeout.)
- Click any of the three buttons, and try to type a new message in the composer.
Expected Behavior
When the underlying tool call / run is interrupted, the pending permission request should be revoked and the dialog dismissed, restoring the composer. Allow/Deny on a prompt that is still displayed should always succeed.
Actual Behavior
- The permission dialog stays pinned above the composer indefinitely; typing new input is blocked.
- Every click sends
POST /api/session/<id>/permission/<id>/reply, which the server answers with 404 and the dialog remains. Server log shows this repeated 7 times within ~90 seconds:
timestamp=2026-10-15T09:02:45.971Z level=INFO role=server http.method=POST http.url=/api/session/ses_…/permission/per_…/reply http.status=404
timestamp=2026-10-15T09:02:52.891Z ... http.status=404
timestamp=2026-10-15T09:02:53.616Z ... http.status=404
timestamp=2026-10-15T09:02:58.625Z ... http.status=404
timestamp=2026-10-15T09:03:11.581Z ... http.status=404
timestamp=2026-10-15T09:03:12.993Z ... http.status=404
timestamp=2026-10-15T09:04:07.130Z ... http.status=404
(i.e. the pending permission request no longer exists server-side, but the UI was never told.)
- The only escape found was abandoning/restarting the session.
Additional Context
- Screenshot available (stuck "Needs permission" dialog with Deny / Always allow / Allow once right after "Tool execution interrupted" on the pending write tool call).
- Possibly related: permission: pending requests destroyed on instance disposal without revocation event; dialog unanswerable, replies 404 forever #52846 — pending permission requests destroyed without a revocation event, leaving an unanswerable dialog that 404s forever. That issue is about instance disposal; here the trigger is a tool interrupt/timeout, but the symptom and root-cause shape (stale pending permission + UI never notified) look like the same family.
- Frequency: reproduced more than once; per user report it happens whenever the permission request hits an exception or wait-timeout, not a one-off.
Activity
opencode-agent commentedon Oct 15, 2026
Thanks for the detailed report. I reproduced this on 2.0.29, and it still happens on the latest
dev(4397ee4).Steps (simulated model; I used a shell
askrule instead ofedit, but both go through the same permission check):askrule, and the "Permission required" prompt appears.PermissionNotFoundError, which matches the 404s in your log.The server drops the pending request when the tool call is interrupted but never sends a
permission.repliedevent, so the client is never told to remove the prompt. In the terminal UI, pressing Enter clears the prompt locally after the failed reply. The Desktop app keeps it and blocks the composer, as you describe.The recording and screenshot below show the prompt still on screen after the interrupt, and the script below reproduces it.
Related: #52846 (the same stale prompt after location disposal or idle eviction), plus #52526 and #29422 (the same interrupt case, both closed).
recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.