Skip to content

[Fix] Task history disappears when user reopens a task - #1319

Draft
zoomote[bot] wants to merge 1 commit into
mainfrom
fix/preserve-task-history-25qz019og2l3b
Draft

[Fix] Task history disappears when user reopens a task#1319
zoomote[bot] wants to merge 1 commit into
mainfrom
fix/preserve-task-history-25qz019og2l3b

Conversation

@zoomote

@zoomote zoomote Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

​Created by Roomote. Follow up by mentioning @roomote, in the web UI, or in Discord.

What changed

  • Preserve finalized reasoning and other saved messages while a task is rehydrated for resume.
  • Distinguish missing, invalid, and unreadable task history from an explicitly empty history instead of converting failures to an empty conversation.
  • Stop abandoned history-task hydration before it can persist after eviction.
  • Abort delegated-parent reopening when its saved UI history cannot be loaded safely.
  • Add deterministic regression coverage for failed hydration, finalized reasoning, and the resume/eviction race.

Why this change was made

Reopening or quickly leaving a saved task could replace valid history with an empty or shortened message list. This resolves #1279 and extends the lifecycle and persistence safety work tracked by #355 and #208.

Impact

Users keep their last saved task content when reopening or resuming tasks. Temporary storage failures no longer become destructive empty writes, and stale task instances cannot write after being evicted.

Related PRs

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.07407% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/task/Task.ts 70.00% 2 Missing and 1 partial ⚠️
src/core/webview/ClineProvider.ts 0.00% 3 Missing ⚠️
src/core/task-persistence/taskMessages.ts 92.85% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@martin-rueegg

Copy link
Copy Markdown

Looks like this might also contribute to fixing some of the things I've experienced in #1231, too

@martin-rueegg martin-rueegg left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the fix is the right approach but can be strengthened by using the new merge functionality of the safeWriteJson() method and updating the local copy with the merged result.

@roomote

let fileContent: string
try {
fileContent = await fs.readFile(filePath, "utf8")
} catch (error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before throwing the error, I suggest we wait a random number of milliseconds 10-300 and retry. safe writes move the file away and then the new one in place. hence, there is a split-second where no file is accessible.

Throw if the second try fails as well

export async function saveTaskMessages({ messages, taskId, globalStoragePath }: SaveTaskMessagesOptions) {
const taskDir = await getTaskDirectoryPath(globalStoragePath, taskId)
const filePath = path.join(taskDir, GlobalFileNames.uiMessages)
await safeWriteJson(filePath, messages)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should apply the new merge-pattern provided by #1261

the same should be done here:

export async function saveApiMessages({
messages,
taskId,
globalStoragePath,
}: {
messages: ApiMessage[]
taskId: string
globalStoragePath: string
}) {
const taskDir = await getTaskDirectoryPath(globalStoragePath, taskId)
const filePath = path.join(taskDir, GlobalFileNames.apiConversationHistory)
await safeWriteJson(filePath, messages)
}

which is called from
https://github.com/Zoo-Code-Org/Zoo-Code/pull/1319/changes#diff-ec3b024cdaad55c3e92c0d0d4293bbc785e69f76bf646132cb0923f44fb3df22R992

Comment thread src/core/task/Task.ts

private async saveApiConversationHistory(): Promise<boolean> {
try {
await saveApiMessages({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants