Hmbown/CodeWhale · error

Cloud agent sandbox entered state

Error message

Cloud agent sandbox entered state '{state}'.

What it means

While polling sandbox readiness, the provider reported the sandbox reached a terminal bad state (`error`, `destroyed`, or `archived`) instead of `started`/`ready`. The wait aborts immediately since the sandbox will never become ready.

Solutions

  1. Re-dispatch the job to create a fresh sandbox
  2. Check the Daytona dashboard/logs for why the sandbox errored or was destroyed
  3. Increase sandbox TTL or keep-alive settings if archiving is the cause
  4. Retry during lower provider load if boot errors cluster
Defensive patterns

Strategy: retry

Try / catch

match wait_ready(&receipt) {
    Err(e) if e.to_string().contains("state '") && is_terminal_bad_state(&e) => re_dispatch(job),
    Err(e) => bail!(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: A poll response's `state` field equals "error", "destroyed", or "archived" — e.g. the sandbox crashed at boot, was reaped by the provider, or was archived for inactivity before first use.

Common situations: Provider capacity issues causing sandbox boot errors, very short sandbox TTLs, someone else deleting the sandbox, image/setup failure.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/7b936f5404f922e9. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/cloud_dispatch.rs:1608

        }
        let url = Self::control_plane_url(&format!("sandbox/{}", receipt.sandbox_id))?;
        for _ in 0..READY_POLL_ATTEMPTS {
            let response = Self::send_json(
                reqwest::Method::GET,
                &url,
                &api_key,
                serde_json::Value::Null,
            );
            match response {
                Ok(response) if response.status().is_success() => {
                    let text = response.text().unwrap_or_default();
                    if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(&text)
                        && let Some(state) = parsed.get("state").and_then(|v| v.as_str())
                    {
                        match state {
                            "started" | "ready" => return Ok(()),
                            "error" | "destroyed" | "archived" => {
                                bail!("Cloud agent sandbox entered state '{state}'.");
                            }
                            _ => {}
                        }
                    } else {
                        return Ok(());
                    }
                }
                Err(error) => return Err(error),
                Ok(response) => {
                    if response.status().as_u16() == 404 {
                        bail!("Cloud agent sandbox disappeared before it was ready.");
                    }
                }
            }
            std::thread::sleep(READY_POLL_INTERVAL);
        }
        bail!("Cloud agent sandbox was not ready in time.");
    }

View on GitHub (pinned to 73e0f67d83)