Skip to content

[BUG] Many times, it lost my latest session content #1279

Closed
1 of 1 issue completed
Closed

Description

@jiangbing321

Problem (one or two sentences)

Many times, it lost latest session content and it shows "Continue" and "New task" button. I'm sure that the session was normally closed. It lost the critical session content.

Context (who is affected and when)

Image

Reproduction steps

  1. Use Zoocode to do something.
  2. And the session content is ok.
  3. Next time when it open, saveral latest sesson content is gone.

Expected result

The session content is totally saved.

Actual result

It lost the latest session content.

Variations tried (optional)

No response

App Version

Version: 3.76.0 (5b0bcd0)

API Provider (optional)

None

Model Used (optional)

No response

Zoo Code Task Links (optional)

No response

Relevant logs or errors (optional)

Activity

  1. martin-rueegg commented on Aug 19, 2026

    @martin-rueegg

    I've just experienced this too. with the new Intellij plugin v3.78.0

      System Details:
      OS: Windows 11 10.0 (amd64)
      IDE: PhpStorm 2026.2.1 (build PS-262.9437.196)
      Plugin: v3.78.0
      Java: 25.0.3
      JCEF Support: Yes
    

    I've not experienced it with v3.76.0, though.

    Still investigating ...

  2. martin-rueegg commented on Aug 19, 2026

    @martin-rueegg

    Since I'm regularly syncing my history, I checked a previous version of the ui_messages.json, and it confirms that the last

    	{
    		"ts": 1787129798107,
    		"type": "say",
    		"say": "reasoning",
    		"text": "...",
    		"partial": false
    	}

    which was on disk previously, got replaced by

    	{
    		"ts": 1787142723063,
    		"type": "ask",
    		"ask": "resume_completed_task"
    	}

    however, it is to be noted, that the just preceding node is:

    	{
    		"ts": 1787129794658,
    		"type": "say",
    		"say": "api_req_started",
    		"text": "{\"apiProtocol\":\"openai\",\"tokensIn\":0,\"tokensOut\":0,\"cacheWrites\":0,\"cacheReads\":0,\"cost\":0,\"cancelReason\":\"streaming_failed\",\"streamingFailedMessage\":\"Provider ended the request: terminated\"}"
    	},

    in both version. the text says:

    	{
    		"apiProtocol": "openai",
    		"tokensIn": 0,
    		"tokensOut": 0,
    		"cacheWrites": 0,
    		"cacheReads": 0,
    		"cost": 0,
    		"cancelReason": "streaming_failed",
    		"streamingFailedMessage": "Provider ended the request: terminated"
    	}
  3. martin-rueegg commented on Aug 19, 2026

    @martin-rueegg

    Root-cause analysis: trailing truncation in 01a014e4

    1. The anomaly at the end of the history

    The ACH ends with a user turn — there is no assistant response after it:

    • Turn [199] — assistant: reasoning + tool_use read_file (lib/Listener/AppDisableListener.php, id call_00_olWL031VWhaWHwYtUikB9896).
    • Turn [200] — user: tool_result for that read_file ({"status":"approved","feedback":"Well, you're now trying from OUTSIDE docker to reach INSIDE docker ..."}) + an <environment_details> block. The ACH stops here.

    The recovered snapshot ui_messages.1787129799.json (430 events) ends differently from the current ui_messages.json:

    event [428] event [429]
    snapshot (crash time) say:api_req_started {"tokensIn":0,"tokensOut":0,…} say:reasoning — text cut off mid-sentence: "…to run Cypress INSIDE the docker network (via"
    current (reopened) same ask:resume_completed_task

    So the assistant had started streaming a reasoning block (tokensOut:0 — the request was still in flight), and the provider terminated it mid-stream. The reasoning and any subsequent tool calls/file reads were never persisted to the ACH, and the partial reasoning was later overwritten by the resume ask when the task was reopened.

    2. Where this happens in the Zoo-Code source

    The root cause is that a mid-stream API termination is never committed to the conversation history. Three spots in Task.ts:

    • Task.ts:4465-4473 — in attemptApiRequest, the first chunk is wrapped in try/catch (which emits the api_req_failed ask), but the remaining chunks are yield* iterator outside the try/catch. The comment at Task.ts:4426 states this explicitly: "if the api failed mid-stream, it could be in any arbitrary state… that error is handled differently and requires cancelling the task entirely."

    • Task.ts:3577-3581 — the assistant message is saved to the ACH via addToApiConversationHistory(...) only after the streaming loop completes (// Save assistant message BEFORE executing tools). A stream that throws mid-flight never reaches this line, so the partial assistantContent (reasoning + any tool_use blocks) is lost from api_conversation_history.json.

    • Task.ts:3780-3788 — the catch handler in recursivelyMakeClineRequests just return true (end the task), discarding the partially-streamed assistant content without persisting it.

    Summary

    The trailing events (reasoning + tool calls/file reads) are lost in both ACH and UIM because a provider-terminated mid-stream response is abandoned: the streaming loop throws, the addToApiConversationHistory save point is skipped, and the catch block ends the task without flushing the partial assistant turn. The only trace is the truncated say:reasoning captured in the crash-time snapshot — which the reopen/resume flow then replaces with the terminal ask:resume_completed_task.

  4. martin-rueegg commented on Aug 19, 2026

    @martin-rueegg

    @jiangbing321 can you confirm that it might only have happened in cases where the last entry before closing the task was an API error?

  5. jiangbing321 commented on Aug 20, 2026

    @jiangbing321
    Author

    @jiangbing321 can you confirm that it might only have happened in cases where the last entry before closing the task was an API error?
    Thanks a lot!
    It's not an API error. The session was normally closed. The lost contents are often the critical and important conclusion of the LLM.

  6. martin-rueegg commented on Aug 20, 2026

    @martin-rueegg

    @jiangbing321 can you confirm that it might only have happened in cases where the last entry before closing the task was an API error?

    Thanks a lot!
    It's not an API error. The session was normally closed. The lost contents are often the critical and important conclusion of the LLM.

    ok, that means that the analysis above is not the (only) root cause.

  7. zoomote commented on Aug 21, 2026

    @zoomote
    Contributor

    Reproduction and implementation update:

    This remains reproducible on the v3.78 code path. Three current behaviors combine to lose visible history:

    1. readTaskMessages() maps missing, parse, and transient I/O failures to []; resumeTaskFromHistory() then persists that empty result via overwriteClineMessages().
    2. Resume removes every trailing reasoning row, including finalized (partial: false) rows, and persists the shortened history before showing the resume prompt.
    3. An abandoned history-task instance can finish hydration after eviction and still write because ownership/cancellation is not rechecked after the awaited read.

    A completed task also retains terminal completed status after Continue, explaining why later unfinished work reopens with “Continue / New task.”

    I have added this issue as a sub-issue of #355. The implementation will proceed test-first with deterministic persistence tests. An extension-host e2e will be added only for behavior that can be asserted without relying on the sub-millisecond disk race. Related roadmap work: #364, #366, #367, #368, and #370.

  8. zoomote commented on Aug 21, 2026

    @zoomote
    Contributor

    Implementation is ready for review in paired draft PRs:

    The canonical regressions are deterministic task/persistence tests covering missing, invalid, and I/O-failed hydration; finalized trailing reasoning; and eviction while hydration is pending. The existing extension-host resume/evict e2e remains smoke coverage because the public test API cannot seed or inspect ui_messages.json or control the sub-millisecond disk-read window.

  9. edelauna commented on Sep 6, 2026

    @edelauna
    Contributor

    Fixed by #1319 — reopenParentFromDelegation now reads both UI and API history and saves them under the per-file advisory lock before the lifecycle transition fires. restart-persistence.test.ts is the controlled barrier test.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions