Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,9 @@ export class ClineProvider
await this.removeClineFromStack()
}

public async createTaskWithHistoryItem(historyItem: HistoryItem & { rootTask?: Task; parentTask?: Task }) {
public async createTaskWithHistoryItem(
historyItem: HistoryItem & { rootTask?: Task; parentTask?: Task },
): Promise<Task> {
await this.removeClineFromStack()

// If the history item has a saved mode, restore it and its associated API configuration.
Expand Down Expand Up @@ -903,6 +905,40 @@ export class ClineProvider
}
}

// Restore parent-child task relationships if this is a subtask
let restoredParentTask: Task | undefined = undefined
let restoredRootTask: Task | undefined = undefined

if (historyItem.parentTaskId) {
// Try to find the parent task in the current task stack
restoredParentTask = this.clineStack.find((task) => task.taskId === historyItem.parentTaskId)

if (!restoredParentTask) {
// Parent task is not in the stack, try to restore it from history
this.log(`Restoring parent task ${historyItem.parentTaskId} for subtask ${historyItem.id}`)
try {
const { historyItem: parentHistoryItem } = await this.getTaskWithId(historyItem.parentTaskId)
// Recursively restore parent task (which may have its own parent)
restoredParentTask = await this.createTaskWithHistoryItem(parentHistoryItem)
Copy link
Author

Choose a reason for hiding this comment

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

Recursively restored parent tasks will automatically start execution, which interferes with the child task. When createTaskWithHistoryItem is called recursively at line 922, it creates a new Task instance that defaults to startTask: true. This causes the parent's resumeTaskFromHistory() to be invoked, starting its task loop. The parent should only exist in memory for reference - not actively run. Pass startTask: false when constructing the Task for recursive parent restoration to prevent this.

Fix it with Roo Code or mention @roomote and request a fix.

Copy link

Choose a reason for hiding this comment

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

@roomote fix that

Copy link
Author

@roomote roomote bot Nov 4, 2025

Choose a reason for hiding this comment

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

See this task on Roo Code Cloud

Fixed the reported issue. All local checks passed.

View commit | Revert commit

} catch (error) {
this.log(
`Failed to restore parent task ${historyItem.parentTaskId}: ${error instanceof Error ? error.message : String(error)}`,
)
}
}
}

if (historyItem.rootTaskId) {
// Try to find the root task in the current task stack
restoredRootTask = this.clineStack.find((task) => task.taskId === historyItem.rootTaskId)

if (!restoredRootTask && historyItem.rootTaskId !== historyItem.parentTaskId) {
// Root task is different from parent and not in stack
this.log(`Note: Root task ${historyItem.rootTaskId} not found in current stack`)
// We could restore root task here if needed, but usually parent is enough
}
}

const {
apiConfiguration,
diffEnabled: enableDiff,
Expand All @@ -924,8 +960,8 @@ export class ClineProvider
consecutiveMistakeLimit: apiConfiguration.consecutiveMistakeLimit,
historyItem,
experiments,
rootTask: historyItem.rootTask,
parentTask: historyItem.parentTask,
rootTask: restoredRootTask || historyItem.rootTask,
parentTask: restoredParentTask || historyItem.parentTask,
taskNumber: historyItem.number,
workspacePath: historyItem.workspace,
onCreated: this.taskCreationCallback,
Expand Down