Hmbown/CodeWhale · warning
HTTP
Error message
HTTP {status} What it means
During rollback after a label-apply failure, the DELETE teardown call returned a non-success status other than 404 (404 is accepted as already-gone). This intermediate error only controls which final message is emitted: teardown succeeded vs. needs manual cleanup.
Solutions
- Check the inner HTTP status and the API key's permissions
- Look in the Daytona dashboard for the sandbox id named in the final error and delete it manually
- Retry teardown once the provider recovers
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the key can delete sandboxes before dispatch begins check_permission(key, "sandbox:delete")?;
Try / catch
if let Err(undo_error) = teardown(sandbox_id, key) {
error!("manual cleanup required for sandbox {sandbox_id}: {undo_error}");
notify_operator(sandbox_id);
} Prevention
- Grant the dispatch API key full sandbox lifecycle permissions
- Retain the sandbox id in the job record so orphans can be found later
- Periodically sweep for unlabelled sandboxes at the provider
When it happens
Trigger: Compensation DELETE of the just-created sandbox hits 401/403 (bad API key), 409/5xx provider trouble, or a network failure — anything not success or 404.
Common situations: API key lacks delete permission, Daytona outage during rollback, sandbox already in a state that refuses deletion.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Cloud agent create failed
- cloud agent label apply failed
- cloud agent was created but its labels could not be applied…
- Anthropic API error (HTTP )
- build platform HTTP client
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/27bfa2b16ec1e910.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/cloud_dispatch.rs:1562
// (kept there for forward compatibility). Labels are load-bearing:
// the orphan reconciler joins them back to job records, so a
// sandbox without them is untraceable spend. If the PUT fails, the
// already-created sandbox is torn down immediately and create
// fails truthfully — no orphan, retryable — rather than returning
// a receipt the reconciler can never find again.
if let Err(label_error) = Self::put_sandbox_labels(&sandbox_id, &api_key, job) {
let undo = Self::send_json(
reqwest::Method::DELETE,
&Self::control_plane_url(&format!("sandbox/{sandbox_id}"))?,
&api_key,
serde_json::Value::Null,
)
.and_then(|response| {
let status = response.status();
if status.is_success() || status.as_u16() == 404 {
Ok(())
} else {
bail!("HTTP {status}")
}
});
match undo {
Ok(()) => bail!(
"cloud agent created but its labels could not be applied ({}); \
the sandbox was torn down — retry the job.",
sanitize_error(&label_error.to_string())
),
Err(undo_error) => bail!(
"cloud agent {sandbox_id} was created but its labels could not be \
applied ({}) and teardown also failed ({}); the sandbox needs \
manual cleanup at the provider.",
sanitize_error(&label_error.to_string()),
sanitize_error(&undo_error.to_string())
),
}
}
Ok(SandboxReceipt {View on GitHub (pinned to 73e0f67d83)