ACP mode: 'internal RetriableError: WritableIterable is closed' is streamed to the client as assistant message text

,

Where does the bug appear (feature/product)?

Cursor CLI

Describe the Bug

In ACP mode, cursor-agent emits an internal stream error as a normal agent_message_chunk, so it becomes indistinguishable from the assistant’s actual response. The turn is then reported as successful with stopReason: end_turn, giving the client no in-band way to tell that the text isn’t part of the answer.

Steps to Reproduce

Minimal ACP Client, no editor or third party involved:

import json, subprocess, tempfile, threading, time

cwd = tempfile.mkdtemp()
p = subprocess.Popen(["cursor-agent", "--model", "composer-2.5", "acp"],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=cwd, text=True, bufsize=1)
send = lambda o: (p.stdin.write(json.dumps(o) + "\n"), p.stdin.flush())

send({"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,
      "clientCapabilities":{"fs":{"readTextFile":False,"writeTextFile":False},"terminal":False},
      "clientInfo":{"name":"probe","version":"1.0"}}})

done = []
for line in p.stdout:
    o = json.loads(line)
    u = (o.get("params") or {}).get("update") or {}
    if u.get("sessionUpdate") == "agent_message_chunk":
        print("CHUNK:", repr(u["content"]["text"]))
    if o.get("id") == 1 and "result" in o:
        send({"jsonrpc":"2.0","id":2,"method":"session/new","params":{"cwd":cwd,"mcpServers":[]}})
    elif o.get("id") == 2 and "result" in o:
        send({"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{
              "sessionId":o["result"]["sessionId"],
              "prompt":[{"type":"text","text":"Reply with exactly PONG and nothing else."}]}})
    elif o.get("id") == 3:
        print("RESULT:", o.get("result")); break

Actual output:

CHUNK: 'PONG'
CHUNK: '\n\nError: RetriableError: WritableIterable is closed'
RESULT: {'stopReason': 'end_turn'}

Expected Behavior

Either the internal error is handled without being streamed as assistant content, or the turn fails with an error result. Not both a successful end_turn and error text presented as the model’s reply.

Operating System

MacOS

Version Information

cursor-agent 2026.08.11-e8db854

For AI issues: which model did you use?

Compose 2.5

Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

Hey, thanks for the detailed report and especially for the minimal reproducer. It’s really helpful.

You’re right on both points. That WritableIterable is closed text is an internal transient stream error that shouldn’t show up in the assistant response, and the turn shouldn’t report end_turn as a success when this happens. This is a known issue we’re tracking, and I’ve added your repro to it. I can’t share a timeline yet, but I’ll follow up in the thread when there’s an update.

For now, a workaround on your side:

  • The error is transient. Retrying session/prompt in the same session usually works.
  • The extra text always comes as a trailing chunk starting with \n\nError:, after the real answer. You can temporarily filter it client-side.

Let me know if you see other variations of this behavior.