{"record":{"id":"ad6449ae5cb142e9","repo":"Hmbown/CodeWhale","slug":"this-launcher-does-not-support-teardown","errorCode":null,"errorMessage":"this launcher does not support teardown","messagePattern":"this launcher does not support teardown","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/cloud_dispatch.rs","lineNumber":1194,"sourceCode":"    /// Block until the sandbox accepts toolbox calls (bounded poll).\n    fn wait_ready(&self, _receipt: &SandboxReceipt) -> Result<()> {\n        Ok(())\n    }\n    /// Clone the target forge repository inside the sandbox.\n    fn clone_repository(&self, _receipt: &SandboxReceipt, _url: &str, _path: &str) -> Result<()> {\n        bail!(\"this launcher does not support repository clones\")\n    }\n    /// Run one harness command inside the sandbox and return bounded stdout.\n    fn run_harness(&self, _receipt: &SandboxReceipt, _command: &HarnessCommand) -> Result<String> {\n        bail!(\"this launcher does not support harness execution\")\n    }\n    /// Collect the agent's work product from the sandbox.\n    fn collect_patch(&self, _receipt: &SandboxReceipt) -> Result<PatchReceipt> {\n        bail!(\"this launcher does not support patch collection\")\n    }\n    /// Tear the sandbox down. Called on cancel, failure, and completion.\n    fn teardown(&self, _receipt: &SandboxReceipt) -> Result<()> {\n        bail!(\"this launcher does not support teardown\")\n    }\n    /// List Codewhale-dispatch sandboxes with their job labels. Used by the\n    /// reconciler (startup sweep and cancel); not part of the run protocol.\n    fn list_job_sandboxes(&self) -> Result<Vec<LabeledSandbox>> {\n        bail!(\"this launcher does not support sandbox listing\")\n    }\n}\n\n/// One dispatch-labeled sandbox discovered by the reconciler.\n#[derive(Debug, Clone, PartialEq, Eq)]\npub struct LabeledSandbox {\n    pub sandbox_id: String,\n    /// Job id from the `codewhale.job` label, when the label is present.\n    pub job_id: Option<String>,\n}\n\n/// Provider receipt for a created sandbox. `toolbox_url` is the validated\n/// per-sandbox toolbox origin returned by the create call, when present.","sourceCodeStart":1176,"sourceCodeEnd":1212,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/cloud_dispatch.rs#L1176-L1212","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nstruct TestLauncher;\nimpl DaytonaLauncher for TestLauncher {\n    fn create_sandbox(&self, _job: &CloudJob) -> Result<SandboxReceipt> { /* ... */ }\n    // teardown left on trait default\n}\n// after\nimpl DaytonaLauncher for TestLauncher {\n    fn create_sandbox(&self, _job: &CloudJob) -> Result<SandboxReceipt> { /* ... */ }\n    fn teardown(&self, _receipt: &SandboxReceipt) -> Result<()> { Ok(()) }\n}","handlingStrategy":"try-catch","validationCode":"fn supports_teardown(l: &dyn DaytonaLauncher) -> bool { l.wants_teardown_support() } // or track impl capability in your own wrapper enum","typeGuard":"fn is_live_launcher(l: &dyn DaytonaLauncher) -> bool { std::any::TypeId::of::<LiveDaytonaLauncher>() == l.type_id() }","tryCatchPattern":"match launcher.teardown(&receipt) {\n    Err(e) if e.to_string().contains(\"does not support teardown\") => { /* fixture launcher: skip cleanup */ }\n    other => other?,\n}","preventionTips":["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."],"tags":["sandbox","lifecycle","trait-default","cloud-dispatch"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}