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

  1. Ensure the timeout branch builds a checkpoint with reason "api_timeout" and continuable=true before storing the result
  2. Check the Interrupted status transition doesn't clear the checkpoint field
  3. Verify the step counter is incremented before the checkpoint snapshot is taken
  4. 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

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.

Related errors


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)