Hmbown/CodeWhale · error

first timed-out API attempt should reach the test server

Error message

first timed-out API attempt should reach the test server

What it means

Panic from `.expect("first timed-out API attempt should reach the test server")` on a `tokio::time::timeout` wrapping a polling loop. The test awaited the axum test server recording at least one API call within the window after a deliberately timed-out first attempt; if the loop ends without seeing the call, the retry/timeout machinery failed to re-issue the request.

Solutions

  1. Verify the retry path in SubAgentManager actually re-issues the API call after the client timeout
  2. Confirm the mock axum server increments the `calls` counter on each request
  3. Check that the timeout windows (client timeout vs test timeout) leave room for the retry to be observed
  4. Inspect test logs for the first attempt's timeout firing before the loop starts

Example fix

// before
.await.expect("first timed-out API attempt should reach the test server");
// after
.await.unwrap_or_else(|| panic!(
    "no API attempt reached the test server after timeout; calls={}\",
    calls.load(Ordering::SeqCst)"));
Defensive patterns

Strategy: retry

Try / catch

tokio::time::timeout(Duration::from_secs(5), poll_for_call())
    .await
    .unwrap_or_else(|_| panic!("retry never reached test server; calls={}", calls.load(Ordering::SeqCst)));

Prevention

When it happens

Trigger: Running api_timeout_preserves_checkpoint_and_returns_needs_input_without_parking when the sub-agent's retry path does not re-send the API request after the first attempt times out, or the mock server's request counter never increments within the awaited window.

Common situations: A regression in SUBAGENT_API_TIMEOUT retry logic (retries skipped or retried against the wrong client), mock server bound to a different port, or the polling loop checking the wrong counter.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/0d793aa81fbdd241. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/tests.rs:8988

        max_steps: 3,
        token_budget: None,
        wall_time: DEFAULT_CHILD_WALL_TIME,
        input_rx: task_input_rx,
        launch_gate: None,
        _foreground_child_registration: None,
    };
    let task_handle = tokio::spawn(run_subagent_task(task));

    tokio::time::timeout(Duration::from_secs(5), async {
        loop {
            if calls.load(Ordering::SeqCst) >= 1 {
                break;
            }
            tokio::time::sleep(Duration::from_millis(10)).await;
        }
    })
    .await
    .expect("first timed-out API attempt should reach the test server");

    let interrupted_envelope = tokio::time::timeout(Duration::from_secs(5), async {
        loop {
            for env in mailbox_rx.drain() {
                if let MailboxMessage::Interrupted {
                    agent_id: id,
                    reason,
                } = env.message
                {
                    return (id, reason);
                }
            }
            tokio::time::sleep(Duration::from_millis(10)).await;
        }
    })
    .await
    .expect("API timeout should publish an Interrupted mailbox lifecycle event");
    assert_eq!(interrupted_envelope.0, agent_id);

View on GitHub (pinned to 433685b202)