Hmbown/CodeWhale · error

Cloud agent sandbox was not ready in time.

Error message

Cloud agent sandbox was not ready in time.

What it means

Thrown by `wait_ready` in the cloud sandbox provider after the sandbox was created but never reached the `started`/`ready` state within `READY_POLL_ATTEMPTS` polling iterations spaced by `READY_POLL_INTERVAL`. The control plane kept returning a non-success, non-404 response (or an unparseable body with a non-terminal state such as `provisioning`), so the dispatcher gives up rather than waiting forever. This is a provisioning-timeout condition, not an authentication or request-shape failure.

Solutions

  1. Retry the cloud job — sandbox provisioning is often transiently slow; a fresh attempt usually gets a healthy sandbox.
  2. Check the provider (Daytona) status/region health and your quota; reduce load or switch region if the sandbox is stuck provisioning.
  3. Inspect the sandbox by id in the provider dashboard; if it exists but is stuck, delete it manually before retrying so the next dispatch starts clean.
  4. If timeouts are consistently near-miss, increase READY_POLL_ATTEMPTS or READY_POLL_INTERVAL in crates/tui/src/cloud_dispatch.rs for slower-provisioning accounts/images.

Example fix

// before
for _ in 0..READY_POLL_ATTEMPTS {
    // poll ...
    std::thread::sleep(READY_POLL_INTERVAL);
}
bail!("Cloud agent sandbox was not ready in time.");
// after
// rerun the job; if it recurs, raise the poll budget:
const READY_POLL_ATTEMPTS: usize = 120;
const READY_POLL_INTERVAL: Duration = Duration::from_secs(5);
Defensive patterns

Strategy: retry

Try / catch

// the sandbox may simply need longer; retry the whole dispatch with backoff
match dispatch_cloud_job(job) {
    Err(e) if e.to_string().contains("not ready in time") => retry_with_backoff(job, 2),
    other => other,
}

Prevention

When it happens

Trigger: Calling the cloud-agent dispatch path that provisions a sandbox (e.g. starting a cloud job or raising a PR) when the provider's control plane keeps reporting the sandbox in a non-ready state: `GET sandbox/{id}` repeatedly returns 5xx, 429, or a JSON body whose `state` is still provisioning/booting for the entire poll window. Terminal states (`error`, `destroyed`, `archived`) and a 404 bail earlier with distinct messages.

Common situations: Provider outage or degraded region at Daytona; sandbox image pulls are slow (large image, cold cache); provider capacity shortage leaving the sandbox queued; network flakiness between the client and the control plane producing intermittent 5xx during every poll; provider slowed state transitions after an API version change.

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@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/5094a7f94cd588aa. Report an issue: GitHub.

Appendix: source

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

                            "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.");
    }

    fn clone_repository(&self, receipt: &SandboxReceipt, repo_url: &str, path: &str) -> Result<()> {
        let repo_url = validate_git_remote_url(repo_url)?;
        let api_key = Self::api_key()?;
        let url = Self::toolbox_base(receipt)?.join("git/clone")?;
        let body = serde_json::json!({ "url": repo_url, "path": path });
        let response = Self::send_json(reqwest::Method::POST, &url, &api_key, body)?;
        let status = response.status();
        if !status.is_success() {
            bail!("Cloud agent repository clone failed (HTTP {status}).");
        }
        Ok(())
    }

    fn run_harness(&self, receipt: &SandboxReceipt, command: &HarnessCommand) -> Result<String> {
        let api_key = Self::api_key()?;
        let url = Self::toolbox_base(receipt)?.join("process/execute")?;

View on GitHub (pinned to 73e0f67d83)