Skip to content

Sometimes replies to the previous turn (stale context): keeps repeating an earlier command/answer instead of responding to the latest input #16612

Closed as not planned

Description

@leo512zy

Description

When using OpenCode, sometimes the assistant responds to the previous user message/command instead of the most recent one.

In many cases, re-sending the same question/command once makes it recover and respond correctly. However, sometimes it gets “stuck” and keeps repeating the same action/response, as if it’s still processing or replying to an earlier turn in the conversation (stale context / wrong message).

This feels like the latest input is not being applied, or the model is receiving / the UI is displaying an older turn.

Plugins

No response

OpenCode version

v1.2.21

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

Ubuntu 24.04.4 LTS

Terminal

No response

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 8, 2026
  2. bcsgarcia commented on Mar 8, 2026

    @bcsgarcia

    Same behavior here.

    Plugins
    none

    OpenCode version
    v1.2.21

    Steps to reproduce
    No response

    Screenshot and/or share link
    No response

    Operating System
    MacOS Tahoe 26.3

    Terminal
    iTerm Build 3.6.8

  3. dukebw commented on Mar 13, 2026

    @dukebw
    Contributor

    I've noticed the same. This definitely seems like a harness bug.

  4. turcottep commented on Mar 19, 2026

    @turcottep

    Same, happens more on long context, and when switching between build and plan mode

  5. danxdev commented on Mar 29, 2026

    @danxdev

    Same, happens more on long context, and when switching between build and plan mode

    Yep, this combo seems to trigger it more frequently.

  6. HeyMaster311 commented on Apr 1, 2026

    @HeyMaster311

    Happened to me quite frequently these days. Not sure if it has something to do with the to-do list or LSP

  7. 8hantanu commented on Apr 16, 2026

    @8hantanu

    I think this might be specifically related to todo list execution.

    From my sessions, I observed the issue appears when the harness creates a multi-step todo list and executes items sequentially:

    • The first item completes as expected
    • When moving to the second item, the agent switches context and starts acting on a previous prompt

    This suggests the problem may occur during the transition between todo items, where context/state isn’t being carried forward correctly.

  8. turcottep commented on Apr 16, 2026

    @turcottep

    This also happened to me a couple times on the codex cli with gpt-5.4 high, so it may be a model problem

  9. guidomb commented on Apr 22, 2026

    @guidomb

    This is happening to me very frequently, even after updating to 1.4.20

  10. guidomb commented on Apr 22, 2026

    @guidomb

    I've been trying to debug this issue using opencode (with GPT-5.4) and my local opencode database. The following is a summary that the model generated with its research and hypothesis of what the problem could be. I don't have experience with opencode's source code and haven't spent too much time review it so I cannot say with confidence if the LLM analysis is correct but I provided as much information as possible and pointed it to the session where I have experienced the issue. Hope this is helpful for the maintainers to debug the issue. I cannot share the session because it has work related stuff but I can jump into a call if needed to review my session history,


    I did a deeper local investigation against my own OpenCode history and source checkout, and I wanted to share a more concrete hypothesis with examples.

    What I investigated

    I reviewed:

    I specifically inspected session:

    because this is a session where I experienced the drift multiple times.

    Important context

    This session is useful because it does not appear to involve the earlier hypotheses around plan mode or compaction:

    • 0 plan messages
    • 0 compaction summary messages
    • 921 total messages

    So this particular repro does not seem to require:

    • plan/build switching
    • compaction summaries
    • wrong parentID

    That makes me think the problem is more general.

    What I found

    1. The drift happened with the correct latest user turn
      In this session, I sent:

    OK proceed with task 7 then

    The assistant first responded correctly:

    I’m starting Task 7 from the report DSL and runtime boundary first: define the filter/mapping shape, harden the query path for user-driven filters, then layer the report-side filter UI on top.

    But then, in the next assistant step under the same user message, it pivoted back to the previous task and said:

    I’ve finished the Task 6 implementation changes. I’m running the full validation stack now so we can close the task cleanly.

    Then I replied:

    eh? I told you to proceed with task 7

    And the assistant explicitly answered:

    You’re right. I drifted back into Task 6 cleanup instead of moving on to Task 7.

    This seems like a very strong signal that the harness had the correct latest user turn, but the model was still being shown stale execution state from the previous task.

    1. I found repeated stale assistant progress text in the same session
      Later in the same session, after a different user turn about ReportLive tests, the assistant emitted:

    I’m rerunning the ReportLive tests now.

    multiple times, including across later user messages like:

    continue

    This matches the user-visible symptom from #16612 / #19548: the assistant appears to re-anchor to an earlier in-flight activity rather than the latest prompt.

    1. The likely problem is in prompt/history assembly, not parent linkage
      From the DB inspection, the assistant messages were parented to the correct latest user messages. So I do not think this is mainly:
    • wrong parentID
    • wrong thread selection
    • undo restoring the wrong user message

    Instead, it looks more like the next model prompt is being assembled with too much stale assistant-internal execution state.


    Concrete code-path hypothesis

    The most suspicious code path I found is:

    • packages/opencode/src/session/prompt.ts
    • packages/opencode/src/session/message-v2.ts

    Prompt assembly

    SessionPrompt.run calls:
    MessageV2.toModelMessagesEffect(msgs, model)

    and then passes the resulting reconstructed history to the model.

    Message serialization

    In packages/opencode/src/session/message-v2.ts, toModelMessagesEffect(...) serializes all prior assistant messages by replaying:

    • assistant text
    • reasoning
    • step-start
    • tool calls
    • tool results
    • even pending/running tool calls as synthetic interruption results

    Relevant area:

    if (msg.info.role === "assistant") {
      ...
      for (const part of msg.parts) {
        if (part.type === "text") ...
        if (part.type === "step-start") ...
        if (part.type === "tool") ...
        if (part.type === "reasoning") ...
      }
    }

    So the harness is not just replaying “chat history” in a human sense. It is replaying a lot of assistant execution process state.


    Stronger finding: todowrite output is likely contaminating future prompts

    The most concrete issue I found in my drift session is that todowrite output is serialized back to the model as a normal tool result.
    packages/opencode/src/tool/todo.ts returns:

    return {
      title: `${params.todos.filter((x) => x.status !== "completed").length} todos`,
      output: JSON.stringify(params.todos, null, 2),
      metadata: {
        todos: params.todos,
      },
    }

    That means the todo list is stored as plain JSON output for the tool call.
    Then MessageV2.toModelMessagesEffect(...) serializes completed tool outputs back into the model history.

    Why this matters

    In the exact drift turn I inspected, the assistant had just written a todo list whose output contained:

    [
      {
        "content": "Run full validation for completed Task 6 changes",
        "status": "in_progress",
        "priority": "high"
      },
      {
        "content": "Prepare Task 6 for commit once validation is green",
        "status": "pending",
        "priority": "medium"
      }
    ]

    Then after I said:

    OK proceed with task 7 then

    the assistant initially acknowledged Task 7, but immediately after that it pivoted back to:

    I’ve finished the Task 6 implementation changes. I’m running the full validation stack
    now...

    That makes me suspect the model was being shown the stale todowrite JSON from Task 6 in the reconstructed prompt, and it re-anchored on that.

    This feels like a harness bug much more than a raw model bug.


    Why I think this is mostly a harness issue

    I understand that chat APIs require the harness to reconstruct and resend history every turn. That by itself is normal.

    But the harness still decides:

    • which prior messages to keep
    • which tool outputs to replay
    • which assistant intermediate steps to replay
    • which synthetic reminders to inject
    • how pending/running tool calls are represented
    • what counts as “conversation” vs “execution bookkeeping”

    My concern is that OpenCode is currently replaying too much assistant orchestration state as if it were semantically important conversation context.

    In my session, the harness seems to be feeding the model stale items like:

    • prior progress text
    • prior tool/result chatter
    • prior todo JSON with explicit old task labels

    When the next user message is something like:

    • continue
    • OK proceed with task 7 then
      the model may reasonably latch onto the wrong prior task because the harness made that stale task state highly salient.

    So while model behavior may amplify the problem, the root cause still looks primarily harness-side to me.


    Why I do not think the earlier #19548 proposed fix is sufficient

    The earlier hypothesis in #19548 was that older assistant turns were replayed too aggressively, and that trimming historical assistant turns to their last step might fix it.
    That may help somewhat, but based on this session I do not think it is sufficient.
    Reasons:

    1. This session had no plan mode and no compaction, but still drifted badly.
    2. The problem seems to involve not just old assistant text, but also tool outputs, especially todowrite.
    3. A lot of the harmful context is not “final answer text”; it is orchestration state.

    So I suspect the real issue is more like:

    • assistant-internal execution artifacts are leaking into future prompts too aggressively
      not just:
    • older assistant text has too many intermediate steps

    Potential solution directions

    I’m not certain what the final fix should be, but based on this investigation I think maintainers may want to consider something along these lines:

    1. Distinguish conversational history from execution bookkeeping
      Not all assistant parts should have equal weight in reconstructed prompts.

    For example, future prompts may want to preserve:

    • prior user requests
    • final assistant conclusions
    • continuation-critical tool results
      but trim or omit:
    • transient progress narration
    • bookkeeping-only tools
    • internal orchestration state
    1. Avoid replaying todowrite output as normal semantic context
      This seems especially risky because todowrite emits explicit task-state JSON like:
    • Run full validation for completed Task 6 changes

    That is exactly the sort of stale instruction that can cause the model to resume the wrong task later.
    One possibility would be to treat todowrite like UI/session state rather than conversational tool-result history.

    1. Re-evaluate which tool results must be replayed at all
      Some tools are continuation-critical.
      Others are just control-plane / bookkeeping tools.
      It may be helpful to classify tool outputs into categories like:
    • must replay
    • replay only for active turn
    • never replay as model context
    1. Re-evaluate multi-step assistant message replay
      Even without compaction or plan mode, the current serialization appears to make earlier assistant steps very “alive” in later prompts.

    The harness may need to preserve less of:

    • intermediate progress text
    • step-by-step assistant narration
    • in-progress task chatter
      especially for historical turns.

    Minimal concrete example from my session

    Here is the distilled repro shape from ses_2632106b8ffegQNJ16mcGeF12n:

    1. Assistant had old task state in a todo result:
      • Run full validation for completed Task 6 changes
    2. User said:
      • OK proceed with task 7 then
    3. Assistant first said:
      • I’m starting Task 7 ...
    4. Then, under the same user turn, assistant pivoted back to:
      • I’ve finished the Task 6 implementation changes. I’m running the full validation stack now...
    5. User said:
      • eh? I told you to proceed with task 7
    6. Assistant answered:
      • You’re right. I drifted back into Task 6 cleanup instead of moving on to Task 7.

    That sequence looks much more like stale harness context than a simple user/model misunderstanding.


    Summary

    My current best hypothesis is:

    • The issue is primarily in OpenCode’s prompt/history assembly.
    • The most suspicious part is replay of assistant execution state, especially tool outputs like todowrite.
    • Plan/build switching may be a separate bug or amplifier in some sessions, but it is not required for the core drift behavior.
    • The previous “trim historical assistant turns to last step” idea probably addresses only part of the problem.
      If useful, I can also provide more exact timestamps / SQL snippets / code references from the local inspection.

  11. michael-conrad commented on Apr 23, 2026

    @michael-conrad

    As a point of contrast: I'm using ollama cloud glm-5.1 and have not seen this type of behavior. The only real issue I've been having is glm-5.1 switching to Chinese for though processes and dumping that to the console.

  12. assigned and unassigned on Apr 26, 2026
  13. guidomb commented on Apr 29, 2026

    @guidomb

    I am now inclined to think that this was a model related issue, maybe there is something in opencode source code in the way it treats the conversation messages / state that manifest with OpenAI GPT-5.4 but after switching to GPT-5.5 I haven't observed this issue anymore.

  14. removed
    bugSomething isn't working
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  15. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions