{"record":{"id":"eeef62884d0a4dde","repo":"Hmbown/CodeWhale","slug":"agent-agent-id-has-no-continuable-checkpoint-to","errorCode":null,"errorMessage":"Agent {agent_id} has no continuable checkpoint to resume from (continuable={continuable}, messages={messages})","messagePattern":"Agent (.+?) has no continuable checkpoint to resume from \\(continuable=(.+?), messages=(.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":5700,"sourceCode":"            if !resumable {\n                return Err(anyhow!(\n                    \"Cannot resume agent {agent_id}: status is {} ({})\",\n                    subagent_status_name(&agent.status),\n                    policy.describe()\n                ));\n            }\n            let checkpoint = agent\n                .checkpoint\n                .as_ref()\n                .filter(|cp| cp.continuable && !cp.messages.is_empty())\n                .ok_or_else(|| {\n                    let continuable = agent.checkpoint.as_ref().is_some_and(|cp| cp.continuable);\n                    let messages = agent\n                        .checkpoint\n                        .as_ref()\n                        .map(|cp| cp.messages.len())\n                        .unwrap_or(0);\n                    anyhow!(\n                        \"Agent {agent_id} has no continuable checkpoint to resume from (continuable={continuable}, messages={messages})\"\n                    )\n                })?;\n            // Restore the interrupted child's write claim so the resumed loop\n            // stays inside the coordination ledger with the original bounded\n            // scope instead of inheriting the caller's unchecked write surface.\n            // The ledger claim is already namespaced and carries the isolation\n            // flag; both are passed through to the spawn seam.\n            let claim = self\n                .coordination\n                .write_claims\n                .iter()\n                .find(|record| record.claim.owner == agent_id)\n                .map(|record| (record.claim.clone(), record.isolated_worktree));\n            // Preserve the interrupted child's runtime posture (read_only /\n            // denied tools / shell) instead of rebuilding from the caller's\n            // role, which could widen the resumed child's authority.\n            let preserved_profile = self","sourceCodeStart":5682,"sourceCodeEnd":5718,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/subagent/mod.rs#L5682-L5718","documentation":"A resume needs a checkpoint marked continuable with at least one stored message; this error reports that the agent's checkpoint is absent, marked non-continuable, or empty (the message embeds continuable and message-count flags for diagnosis). It usually means the child was interrupted before it processed anything, crashed before its first checkpoint write, or its checkpoint was invalidated on terminal completion.","triggerScenarios":"Resuming an agent interrupted during its very first model turn (zero messages recorded); resuming after a crash that happened before the initial checkpoint persisted; a checkpoint whose continuable flag was cleared (e.g., consumed or invalidated by a terminal transition); interrupt_child building a minimal placeholder checkpoint with empty messages, then someone attempting to resume it.","commonSituations":"Users interrupting a child immediately after spawn and then pressing continue; crash-recovery flows assuming every Interrupted agent has usable history; checkpoints pruned by receipt compaction/archive settings.","solutions":["Inspect the agent's snapshot (get_result_by_ref) and check the checkpoint's continuable flag and message count before resuming","If there is no usable checkpoint, spawn a fresh agent whose prompt summarizes what the interrupted agent was doing","When interrupting programmatically, only interrupt after the child has completed at least one turn so a continuable checkpoint exists"],"exampleFix":"// before\nlet resumed = manager.resume_from_checkpoint_with_policy(\n    handle, runtime, &id, &text, policy)?;\n\n// after\nlet snap = manager.get_result_by_ref(&id)?;\nlet resumable = snap.checkpoint.as_ref()\n    .is_some_and(|cp| cp.continuable && !cp.messages.is_empty());\nif !resumable {\n    return spawn_fresh_with_summary(manager, &id, &text).await;\n}\nlet resumed = manager.resume_from_checkpoint_with_policy(\n    handle, runtime, &id, &text, policy)?;","handlingStrategy":"validation","validationCode":"// Require a usable checkpoint before attempting resume.\nlet snap = manager.get_result_by_ref(&agent_id)?;\nlet has_checkpoint = snap.checkpoint.as_ref()\n    .is_some_and(|cp| cp.continuable && !cp.messages.is_empty());\nanyhow::ensure!(has_checkpoint,\n    \"agent {agent_id} has no continuable checkpoint; respawn instead\");","typeGuard":"fn checkpoint_resumable(snap: &SubAgentResult) -> bool {\n    snap.checkpoint.as_ref()\n        .is_some_and(|cp| cp.continuable && !cp.messages.is_empty())\n}","tryCatchPattern":"On 'no continuable checkpoint', branch on the embedded continuable/messages flags: messages=0 means nothing to replay — respawn with the original task; continuable=false means the checkpoint was invalidated — respawn with any known partial output.","preventionTips":["Only interrupt children after their first completed turn, so checkpoints always carry messages","Treat 'Interrupted with empty checkpoint' as functionally identical to a failed spawn in orchestration logic","Periodically verify checkpoint continuity for long-running children you intend to resume"],"tags":["subagent","rust","resume","checkpoint","missing-state"],"backgroundTag":"missing-saved-state","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}