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

  1. Implement fn teardown in your DaytonaLauncher impl to call the provider's sandbox delete endpoint.
  2. If this is a test fixture, either record the teardown call or skip teardown expectations instead of calling through the default stub.
  3. 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

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


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)