Hmbown/CodeWhale · error
this launcher does not support teardown
Error message
this launcher does not support teardown
What it means
The DaytonaLauncher trait provides default implementations for lifecycle methods after create_sandbox so partial test fixtures can compile; teardown is one of these stubs. Hitting this error means the launcher implementation in use never overrode teardown, so the sandbox cannot be torn down through this handle. It is a capability/stub error, not a provider failure.
Solutions
- Implement fn teardown in your DaytonaLauncher impl to call the provider's sandbox delete endpoint.
- If this is a test fixture, either record the teardown call or skip teardown expectations instead of calling through the default stub.
- Ensure production paths use LiveDaytonaLauncher, which overrides the full run protocol.
Example fix
// before
struct TestLauncher;
impl DaytonaLauncher for TestLauncher {
fn create_sandbox(&self, _job: &CloudJob) -> Result<SandboxReceipt> { /* ... */ }
// teardown left on trait default
}
// after
impl DaytonaLauncher for TestLauncher {
fn create_sandbox(&self, _job: &CloudJob) -> Result<SandboxReceipt> { /* ... */ }
fn teardown(&self, _receipt: &SandboxReceipt) -> Result<()> { Ok(()) }
} Defensive patterns
Strategy: try-catch
Validate before calling
fn supports_teardown(l: &dyn DaytonaLauncher) -> bool { l.wants_teardown_support() } // or track impl capability in your own wrapper enum Type guard
fn is_live_launcher(l: &dyn DaytonaLauncher) -> bool { std::any::TypeId::of::<LiveDaytonaLauncher>() == l.type_id() } Try / catch
match launcher.teardown(&receipt) {
Err(e) if e.to_string().contains("does not support teardown") => { /* fixture launcher: skip cleanup */ }
other => other?,
} Prevention
- Only invoke the full lifecycle (teardown/collect/list) on launchers that override it.
- Keep test fixtures' usage confined to create_sandbox/wait_ready paths.
- Wrap the trait in an adapter that reports capability flags.
When it happens
Trigger: Calling launcher.teardown(&receipt) on a launcher whose impl relies on the trait's default body — typically a test recorder or partial fixture — on cancel, failure, or completion of a dispatched cloud job.
Common situations: Running cloud dispatch against a test/fake launcher, or wiring a custom launcher that implements only create_sandbox (and maybe wait_ready) and then letting the runner cancel or finish a job.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- this launcher does not support sandbox listing
- Cloud agent sandbox entered state
- Agent not found
- Agent Mail can be canceled only while queued
- Cannot queue a parent message for agent
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ad6449ae5cb142e9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/cloud_dispatch.rs:1194
/// Block until the sandbox accepts toolbox calls (bounded poll).
fn wait_ready(&self, _receipt: &SandboxReceipt) -> Result<()> {
Ok(())
}
/// Clone the target forge repository inside the sandbox.
fn clone_repository(&self, _receipt: &SandboxReceipt, _url: &str, _path: &str) -> Result<()> {
bail!("this launcher does not support repository clones")
}
/// Run one harness command inside the sandbox and return bounded stdout.
fn run_harness(&self, _receipt: &SandboxReceipt, _command: &HarnessCommand) -> Result<String> {
bail!("this launcher does not support harness execution")
}
/// Collect the agent's work product from the sandbox.
fn collect_patch(&self, _receipt: &SandboxReceipt) -> Result<PatchReceipt> {
bail!("this launcher does not support patch collection")
}
/// Tear the sandbox down. Called on cancel, failure, and completion.
fn teardown(&self, _receipt: &SandboxReceipt) -> Result<()> {
bail!("this launcher does not support teardown")
}
/// List Codewhale-dispatch sandboxes with their job labels. Used by the
/// reconciler (startup sweep and cancel); not part of the run protocol.
fn list_job_sandboxes(&self) -> Result<Vec<LabeledSandbox>> {
bail!("this launcher does not support sandbox listing")
}
}
/// One dispatch-labeled sandbox discovered by the reconciler.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LabeledSandbox {
pub sandbox_id: String,
/// Job id from the `codewhale.job` label, when the label is present.
pub job_id: Option<String>,
}
/// Provider receipt for a created sandbox. `toolbox_url` is the validated
/// per-sandbox toolbox origin returned by the create call, when present.View on GitHub (pinned to 73e0f67d83)