[MODEL] Opus 5 continues past stop point and fabricates a user turn inline (bare `user` separator, 590K context) — regression of #43572

Status Open
Reported on v2.1.247
Maintainer reply None cached
Activity 0 comments · opened Aug 29, 2026

Summary

In a long-context session (590K cached input tokens), Opus 5 ended a normal status report and then continued generating past its stop point, emitting the literal token user followed by a fabricated user message. All of it is a single assistant record in the transcript — there is no corresponding user record anywhere in the file.

This is the \n\nHuman:-continuation failure mode reported in #43572 (closed COMPLETED, 2026-04, Opus 4.x era), reappearing on Opus 5 with a different separator token (user rather than Human:). Related earlier reports: #57928, #60360, #66267, #70543 — all closed.

What happened

The assistant's final text block ends like this (the last line is the fabrication):

...<final line of the assistant's own status report>

user"a bit slow, I'm going to sleep, I'll check your results tomorrow"

(The session is not in English; the fabricated line is translated here. It is a plausible, in-context thing for the user to say at that moment. The user confirms they never wrote it.)

Note there is no whitespace or newline between user and the fabricated content — the model emitted the role separator inline and kept going.

Why this one is worth reopening the thread

  • Model is Opus 5 (claude-opus-5), CLI 2.1.247. #43572 was fixed for the Opus 4.x generation.
  • Separator token differs: prior reports centered on Human:. This is the bare lowercase user, which suggests a mitigation keyed to the Human: string would not catch it.
  • Clean transcript-level evidence: exactly one record, type: assistant, role: assistant, containing both the legitimate report and the fabricated user turn. 375 genuine user records exist in the file; none contains the fabricated text.

Trigger conditions

| Field | Value |
|---|---|
| Model | claude-opus-5 |
| CLI version | 2.1.247 |
| Platform | macOS (darwin 24.6.0) |
| cache_read_input_tokens | 590,242 |
| output_tokens | 264 |
| stop_reason | end_turn |
| Preceding input | tool_result (a Monitor start), not a user message |
| Session shape | long-running agentic session, many background tasks |

The immediately preceding record is a tool_result, not user input. This matches the "near-empty input state at the end of a long context" pattern described in #57928: with no fresh user turn to respond to, the model degrades toward base-completion behavior and continues the transcript with what a user would plausibly say next.

Transcript record shape (sanitized)

{
  "type": "assistant",
  "message": {
    "role": "assistant",
    "model": "claude-opus-5",
    "content": [{"type": "text", "text": "<report>\n\nuser<fabricated user message>"}],
    "stop_reason": "end_turn",
    "usage": {
      "input_tokens": 2,
      "cache_read_input_tokens": 590242,
      "output_tokens": 264
    }
  },
  "version": "2.1.247"
}

Impact

In an agentic setup this is a self-authorization vector. A fabricated user turn can:

  • supply consent the user never gave;
  • redirect the session onto an invented task (as in #64260);
  • survive /compact and become indistinguishable from real user history (as in #70543).

The user here caught it only because the fabricated line was visible in the rendered output. Had the model emitted it in a position where the harness re-ingested it as input, it would have been acted on silently.

Suggested direction

  • Detection should key on role-separator continuation generally, not the Human: literal specifically — this instance used bare user.
  • Consider a transcript-level invariant: text matching a role separator inside an assistant content block is a defect regardless of the surrounding tokens.
  • The "long context + last input is a tool_result, not a user turn" combination looks like the reproducible trigger and may be worth targeting directly.

Repro

Not reliably reproducible on demand — it is an intermittent long-context degradation. The conditions under which it occurred are in the table above. I have the transcript record and can share the sanitized JSON line with the exact byte offsets on request.

View original on GitHub ↗