You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tui: reverting during generation restores the prompt but does not revert #57383
While a turn is streaming, Message Actions → Revert puts the user message back into the prompt, but nothing is reverted and the turn keeps running. session.revert.stage returns SessionBusyError while execution is active; the TUI shows it only as a toast, after the prompt has already been filled. Pressing Enter then sends the restored text as a new message.
This is the same symptom as #53159, which is the likely duplicate. #53159 was closed without a fix shipping in v2: its fix PR #53161 ("fix(tui): abort running turn before reverting a message") was closed unmerged, and the v2.1.0 code still fills the prompt before attempting the revert.
Expected: either leave the prompt untouched when the revert fails, or ask for confirmation that reverting will stop the running turn, then interrupt, wait, and stage (the same order /undo uses).
Plugins
none
OpenCode version
2.1.0
Steps to reproduce
Start a prompt that streams for a while.
While it runs, open a user message's actions and choose Revert.
The prompt is filled, the turn keeps running, and no revert happens.
Thanks for the clear report. I could reproduce this on 2.1.0, and it still happens on the latest dev (d814879).
What I did, using a simulated model that streams a long reply:
Sent a prompt and, while the reply was still streaming, opened the user message's Message Actions (through /timeline).
Chose Revert.
The prompt was filled with the old message immediately, and a Session is busy: ses_… toast appeared. The turn was not interrupted and streamed to the end. The original message and the reply stayed in the transcript, so nothing was reverted, and the old text was left in the prompt, ready to be sent again.
The Revert action fills the prompt before it attempts the revert and never interrupts the running turn, unlike /undo, which interrupts, waits, stages and only then fills the prompt. The recording and screenshots below show it, and the script below reproduces it.
Related: #53159 (same symptom on v1; its fix PR #53161 was not merged), #14014 and #43670 (the same problem in the Web UI).
recording.mp4
Reproduction script (drive.ts)
// Repro for anomalyco/opencode#57383: Message Actions -> Revert while a turn is// streaming fills the prompt, but the revert fails (session busy) and the turn keeps running.import{Effect}from"effect"import{Llm,OpenCodeDriver}from"opencode-drive"constlong=Array.from({length: 40},(_,i)=>`Chunk${i+1}`).join("\n\n")exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),project: {git: true,files: {"src/value.ts": "export const value = 1\n"}},tui: {recording: true,keypressOverlay: true},},({ ui, llm })=>Effect.gen(function*(){// A slow streaming response so the turn is still running when we revert.yield*llm.queue(Llm.text(long,{delay: 300,chunkSize: 5}))yield*ui.submit("Write a long answer about value.ts")yield*Effect.sleep(5000)yield*ui.screenshot("01-streaming")// Open the timeline and choose the user message -> Message Actionsyield*ui.type("/timeline")yield*Effect.sleep(500)yield*ui.enter()yield*Effect.sleep(1000)yield*Effect.sleep(500)yield*ui.screenshot("02-timeline")yield*ui.enter()yield*ui.waitFor("Message Actions",{timeout: 15000})yield*ui.screenshot("03-message-actions")// Pick "Revert"yield*ui.type("Revert")yield*Effect.sleep(300)yield*ui.enter()yield*Effect.sleep(1500)yield*ui.screenshot("04-after-revert")// The turn keeps streaming and the old message is still there.yield*Effect.sleep(4000)yield*ui.screenshot("05-still-running")// Let the turn finish: it was never interrupted, and nothing was reverted.yield*Effect.sleep(15000)yield*Effect.sleep(1500)yield*ui.screenshot("06-turn-finished-not-reverted")}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Activity
opencode-agent commentedon Oct 20, 2026
Thanks for the clear report. I could reproduce this on 2.1.0, and it still happens on the latest
dev(d814879).What I did, using a simulated model that streams a long reply:
/timeline).The prompt was filled with the old message immediately, and a
Session is busy: ses_…toast appeared. The turn was not interrupted and streamed to the end. The original message and the reply stayed in the transcript, so nothing was reverted, and the old text was left in the prompt, ready to be sent again.The Revert action fills the prompt before it attempts the revert and never interrupts the running turn, unlike
/undo, which interrupts, waits, stages and only then fills the prompt. The recording and screenshots below show it, and the script below reproduces it.Related: #53159 (same symptom on v1; its fix PR #53161 was not merged), #14014 and #43670 (the same problem in the Web UI).
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.yassine-safraoui commentedon Oct 20, 2026
Omg you guys really cooked with the opencode-agent 😵