warpdotdev/warp · error
Truncated tasks for forked conversation at block are empty f
Error message
Truncated tasks for forked conversation at block are empty for conversation {}. What it means
In the fork-at-block flow of BlocklistAIHistoryModel, each existing task is truncated at the fork point (`truncated_task` computed per task, `None` when the task has nothing past/before the fork). If every task truncates to None — or the conversation has no tasks at all — `truncated_tasks` is empty and the model refuses to build the fork because there would be no content to persist or show.
Source
Thrown at app/src/ai/blocklist/history_model.rs:1854
if truncated_task.messages.is_empty() {
return None;
}
if let Some(fork_point_exchange) = fork_point_exchange_by_task.get(t.id()) {
reconcile_dangling_tool_calls_in_forked_task(
&mut truncated_task,
&source_task.messages,
&fork_point_exchange.added_message_ids,
);
}
Some(truncated_task)
} else {
None
}
})
.collect();
if truncated_tasks.is_empty() {
return Err(anyhow!(
"Truncated tasks for forked conversation at block are empty for conversation {}.",
conversation.id()
));
}
let updated_tasks_with_new_ids =
update_forked_task_properties(truncated_tasks, prefix, false, title_override);
let Some(sqlite_sender) = GlobalResourceHandlesProvider::as_ref(app)
.get()
.model_event_sender
.clone()
else {
return Err(anyhow!("No sqlite sender available."));
};
// We preserve reverted action IDs. Orphaned IDs (for actions not in fork) are harmless.
// The reverted states are only copied to the new conversation if the revert happened before the user clicked fork,View on GitHub (pinned to e72fd7aacb)
Solutions
- Verify the conversation actually has tasks loaded (hydrated from cloud/DB) before offering fork-at-block in the UI
- Before calling, check that at least one task's messages intersect the fork exchange's added_message_ids
- If tasks should exist, wait for hydration to complete and retry the fork
- Surface a user-facing 'nothing to fork at this block' message instead of an internal anyhow error
Example fix
// before
let forked = model.fork_conversation_at_block(conv_id, exchange_id)?;
// after: guard the precondition at the call site
let has_content = model
.conversation(&conv_id)
.map(|c| !c.tasks().is_empty())
.unwrap_or(false);
anyhow::ensure!(has_content, "Conversation has no tasks to fork at this block");
let forked = model.fork_conversation_at_block(conv_id, exchange_id)?; Defensive patterns
Strategy: validation
Validate before calling
// Before forking at a block, confirm the conversation has tasks that cross the fork point.
let conv = BlocklistAIHistoryModel::as_ref(ctx).conversation(&conversation_id);
anyhow::ensure!(
conv.as_ref().map(|c| !c.tasks().is_empty()).unwrap_or(false),
"Conversation has no tasks to fork at this block"
); Type guard
fn can_fork_at_block(conv: &AIConversation, fork_point_exchange: &AIExchange) -> bool {
!conv.tasks().is_empty()
&& conv
.tasks()
.iter()
.any(|t| messages_intersect(t, &fork_point_exchange.added_message_ids))
} Try / catch
match model.fork_conversation_at_block(conv_id, exchange_id) {
Ok(forked) => forked,
Err(e) if e.to_string().contains("Truncated tasks for forked conversation") => {
// benign precondition failure: tell the user there is nothing to fork here
show_info_toast("Nothing to fork at this block");
return Ok(None);
}
Err(e) => return Err(e),
} Prevention
- Disable the fork-at-block affordance for conversations with no tasks
- Wait for cloud/DB hydration of tasks before enabling fork
- Log truncated-task counts per fork attempt to catch truncation-logic regressions early
When it happens
Trigger: Calling fork-at-block on a conversation where no task's messages intersect the fork_point_exchange.added_message_ids: the chosen block precedes all task content, the exchange's message ids belong to no task, or the conversation's tasks have not been loaded/hydrated yet (cloud or DB fetch still in flight).
Common situations: Fork clicked on the very first block before any agent turn; forking a cloud conversation whose tasks are not yet hydrated locally; fork-point exchange id pointing at a system/placeholder exchange with no task messages.
Related errors
- hydrate_remote_child_placeholder_with_cloud_transcript: loca
- createSemanticTokens: mode "${modeName}" not found in modeId
- Expected JSON object with 'reviews' key
- Invalid repo format: '{}'. Expected 'owner/repo' or 'https:/
- No updates requested
AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16).
Data as JSON: /api/errors/2b3c6e829673f035.
Report an issue: GitHub.