{"record":{"id":"c75c0e2bccd4c4db","repo":"Hmbown/CodeWhale","slug":"lane-was-stopped-before-tmux-launch","errorCode":null,"errorMessage":"lane `{}` was stopped before tmux launch","messagePattern":"lane `(.+?)` was stopped before tmux launch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/lane/src/runtime.rs","lineNumber":802,"sourceCode":"                }\n                spawned.set(true);\n                Ok(())\n            },\n            || {\n                stop_tmux_session(&socket, &session)?;\n                rolled_back.set(true);\n                Ok(())\n            },\n        ) {\n            Ok(true) => {}\n            Ok(false) => {\n                if let Some(path) = environment_path.as_deref() {\n                    remove_file_if_present(path)?;\n                }\n                let mut stopped_record = proposed_record;\n                stopped_record.stopped_at = record.stopped_at.clone();\n                self.cleanup_worktree(&stopped_record)?;\n                bail!(\"lane `{}` was stopped before tmux launch\", record.id);\n            }\n            Err(error) => {\n                if let Some(path) = environment_path.as_deref() {\n                    let _ = remove_file_if_present(path);\n                }\n                if !spawned.get() || rolled_back.get() {\n                    let _ = registry.mark_terminal_if_active(record, LaneStatus::Failed)?;\n                    let mut failed_record = proposed_record;\n                    failed_record.stopped_at = record.stopped_at.clone();\n                    self.cleanup_worktree(&failed_record)?;\n                }\n                return Err(error);\n            }\n        }\n        Ok(())\n    }\n\n    fn attach_command(&self, record: &LaneRecord) -> Option<String> {","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/lane/src/runtime.rs#L784-L820","documentation":"This is the lane-stopped-during-start guard on the real (non-dry-run) tmux launch path. If the lane's stop flag/record indicates the lane was stopped while the tmux launch was being prepared, the runtime cleans up the environment file and worktree, marks the record stopped, and bails instead of starting a lane someone asked to stop. Like 614 it enforces 'stop wins over in-flight start'.","triggerScenarios":"Calling `start` on a lane whose record gets stopped between the start entry point and the tmux spawn — a concurrent `stop`/`reconcile` on the same lane id, or a pre-existing stopped_at set on the record that start detected late.","commonSituations":"A user stops a slow-starting lane (long worktree setup) while start is in flight; an orchestrator's timeout kills the lane mid-start; duplicate start invocations where a first one already stopped the record.","solutions":["Confirm the lane's current state with stop/log inspection, then start it again if a running lane is actually wanted.","Serialize start/stop per lane id in the calling layer to avoid interleaving.","If the stop was unintended, restart the lane — the record was left cleanly stopped with worktree cleaned.","If triggered with no concurrent stop, check the record's stopped_at/log for who set the stop and whether registry state is corrupt."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't call stop while a start for the same lane is in flight; queue operations per lane.","Give starts a chance to finish before applying orchestration timeouts.","Treat this as a clean no-op, not a crash: the lane is left stopped and tidy."],"tags":["race-condition","lifecycle","tmux"],"backgroundTag":"invalid-state-transition","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"}