Hmbown/CodeWhale · error
timeout should preserve checkpoint
Error message
timeout should preserve checkpoint
What it means
Panic from `.expect("timeout should preserve checkpoint")`: the Interrupted SubAgentResult has `checkpoint: None`. An API timeout must snapshot conversation state into a continuable checkpoint (reason "api_timeout", continuable true, steps_taken 1), and this assert shows no checkpoint was captured.
Solutions
- Ensure the timeout branch builds a checkpoint with reason "api_timeout" and continuable=true before storing the result
- Check the Interrupted status transition doesn't clear the checkpoint field
- Verify the step counter is incremented before the checkpoint snapshot is taken
- Trace where SubAgentResult.checkpoint is set and confirm the timeout path reaches it
Example fix
// before
.expect("timeout should preserve checkpoint")
// after
.unwrap_or_else(|| panic!("Interrupted result has no checkpoint; status={:?}", interrupted.status)) Defensive patterns
Strategy: type-guard
Type guard
fn preserved_checkpoint(r: &SubAgentResult) -> Option<&Checkpoint> {
r.checkpoint.as_ref().filter(|c| c.continuable)
} Try / catch
let checkpoint = interrupted.checkpoint.as_ref()
.unwrap_or_else(|| panic!("checkpoint lost on api_timeout interruption")); Prevention
- Construct the checkpoint in the same function that sets Interrupted status
- Assert checkpoint presence invariants at the manager boundary, not only in tests
- Keep checkpoint fields (reason, continuable, steps) immutable once built
When it happens
Trigger: The API-timeout interruption path completes without building/persisting a checkpoint on the result, or the checkpoint field is cleared before the result is stored.
Common situations: Refactor moving checkpoint construction to a path not taken on timeouts; checkpoint dropped during status transition to Interrupted; steps counter reset before snapshot.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- sub-agent task must not park waiting for checkpoint input
- Agent has no continuable checkpoint to resume from…
- Agent not found
- Agent not found
- agent should stay registered
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/311525fd02698203.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/tests.rs:9034
.expect("sub-agent task should finish");
assert_eq!(
calls.load(Ordering::SeqCst),
SUBAGENT_API_TIMEOUT_MAX_RETRIES.saturating_add(1) as usize,
"needs-input interruption must not park for continuation; the API call \
is retried up to the timeout-retry budget, then stops"
);
let interrupted = {
let manager = manager.read().await;
manager
.get_result(&agent_id)
.expect("agent should stay registered")
};
assert!(matches!(interrupted.status, SubAgentStatus::Interrupted(_)));
let checkpoint = interrupted
.checkpoint
.as_ref()
.expect("timeout should preserve checkpoint");
assert_eq!(checkpoint.reason, "api_timeout");
assert!(checkpoint.continuable);
assert_eq!(checkpoint.steps_taken, 1);
assert!(
checkpoint
.messages
.iter()
.any(|message| message_text(message).contains("Inspect checkpoint behavior")),
"checkpoint should preserve local child prompt: {checkpoint:?}"
);
assert!(interrupted.needs_input.is_some());
let ctx = runtime.context.clone();
let worker_record = {
let manager = manager.read().await;
manager.get_worker_record(&agent_id)
};
let projection =View on GitHub (pinned to 433685b202)