Skip to content

compact silently lands reasoning-only (empty-body) summaries, causing irrecoverable context loss #44080

Closed as not planned

Description

@Thexinyi

Summary

When the model used for /compact returns a response containing only reasoning parts and no text part, opencode lands that empty-body message as the session summary and reports compact as successful. The epoch replacement then permanently destroys the original conversation history — yet everything reports success, so the agent continues with an essentially empty (corrupted) context and no warning.

Reproduction — 100% reproducible (2/2 triggers)

  • opencode v1.18.21 (latest)
  • Model: opencode-go/glm-5.3 (reasoning model)
  • Triggered compaction twice on this model; both times compact reported success while the summary message had only a reasoning part and no text part, and the original history was lost.

Steps:

  1. Use opencode-go/glm-5.3 in a session.
  2. Trigger /compact.
  3. Compact reports success; the resulting summary message has no text body; the original history is gone and cannot be recovered.

Relationship to #41571

Shares the same core failure as #41571 (Kimi K3-256k): a reasoning model produces a reasoning-only summary (no text part), opencode marks it summary: true, lands it, and swaps in an empty summary — silently dropping history. #41571 traces this to the v1.18.15 serialize() flattening change in compaction.ts (history flattened to a wall of plain text → reasoning model analyzes instead of summarizing). opencode-go/glm-5.3 on v1.18.21 exhibits the identical symptom at a 100% rate, suggesting the serialize-format issue affects reasoning models broadly, not just k3-256k. (I have not yet read compaction.ts to confirm glm-5.3's exact trigger mechanism, but the symptom + 100% rate + reasoning-model + same serialize code path make a shared root cause highly likely.)

Additional proposals

  • L0 (stream layer): detect/reject reasoning-only (no-text-part) responses as incomplete at stream end — upstream defense before compaction even runs.
  • Structural detection basis: per the @opencode-ai/sdk Part union, TextPart (type:"text") and ReasoningPart (type:"reasoning") are independent union members — a reasoning-only response has no text part at all and is structurally detectable, not a length-threshold heuristic (negligible false-positive risk).
  • Irrecoverability: once the epoch is replaced, the source material is destroyed, so any retry afterward is useless — the failure is silent and permanent. The failure must be caught before epoch replacement.

Expected behavior

  • Compact should fail and retry the LLM while source material still exists when the produced summary has no non-empty TextPart — not land it and replace the epoch.
  • The success/"compacted" marker must not be set until the summary passes body validation.

Suggested fix

Add a hasNonEmptyTextBody(message) check (iterate message.parts; require at least one type === "text" with non-whitespace content) at:

  • L0 (stream layer): at stream end, reject reasoning-only responses as incomplete.
  • L1 (compact landing): before epoch replacement, validate the summary body; on failure, retry the LLM (source still intact) instead of landing.

The same detection function can live in the SDK so plugins/tools share one definition. This is the "at minimum detect empty summaries and fail" bottom-line from #41571, plus an upstream L0 defense.

Impact

  • Severity: high — irrecoverable, silent context loss; the agent continues on a broken session with no warning because the compacted flag is set despite no real content.

Environment

  • opencode v1.18.21 (latest)
  • Model: opencode-go/glm-5.3 (reasoning model)
  • Repro rate: 2/2 (100%)

Activity

  1. github-actions commented on Aug 22, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct (e.g., specific to stream interruption rather than the serialization format change), please clarify how it differs from #41571.

  2. JeTSpice commented on Sep 18, 2026

    @JeTSpice

    Edit: Looks like this is fixed in 1:18:31

    Also experiencing this. Projects are needing to be restarted in a new session and context re-established.
    Constantly getting this after compacting a session:
    Error from provider (Console): OpenCode's free tier can only be used from within OpenCode.

  3. pauldupuyjr commented on Oct 2, 2026

    @pauldupuyjr

    This still reproduces on current dev (after v1.18.34), so it was not fixed in 1.18.31. With a reasoning model whose compaction output runs out on reasoning, or is cut off by the length limit, the empty or partial summary is accepted as the compaction boundary and the earlier history is dropped.

    I have a fix with regression tests that re-derives the guard from #42063 (closed for age, not rejected) and also rejects summaries cut off by finish: "length". Opening it as a PR now; happy to adjust if @rekram1-node already has this in progress.

  4. LegendaryFire commented on Oct 5, 2026

    @LegendaryFire

    This is an issue I'm also running into with OpenCode v2.0.22, however has happened for a few versions already. #53242

  5. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.

    — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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