{"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":"anyhow::Error","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/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/lane/src/runtime.rs#L784-L820","documentation":"mark_running_if_pending_with returns Ok(false) when the lane stopped concurrently while the tmux launch was in flight. The runtime removes the private environment file, adopts the stopped timestamp, cleans up the lane's worktree, and bails — leaving a consistent Stopped record instead of resurrecting a Running lane the user asked to stop.","triggerScenarios":"A stop request (or fenced terminal transition) landing between the start's beginning and its Pending->Running commit for the same lane — e.g. a UI stop button clicked while start is still spawning tmux, or automation issuing stop immediately after start.","commonSituations":"Interactive lane managers where users cancel during launch; scripts that start and immediately stop on timeout; concurrent processes operating one lane id without coordination.","solutions":["Accept the outcome: refetch the lane record — it is Stopped with the worktree cleaned up; do not retry the start unless intended","Guard against the race by waiting for start to return before issuing stop","Use fences/registry transitions to serialize concurrent lifecycle operations on one lane"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match runtime.start(&registry, &mut record, &spec) {\n    Ok(()) => { /* running */ }\n    Err(err) if err.to_string().contains(\"stopped before tmux launch\") => {\n        // Concurrent stop won: environment file removed and worktree cleaned.\n        let fresh = registry.get(&record.id)?.expect(\"lane exists\");\n        assert_eq!(fresh.status, LaneStatus::Stopped);\n        return Ok(()); // user asked to stop; that is the achieved state\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Serialize lifecycle calls per lane (lock or single owner) instead of racing start/stop","In UIs, disable stop until start completes (or coalesce the intent)","After this error, always refetch the record before further operations"],"tags":["rust","lane","tmux","race-condition","lifecycle"],"backgroundTag":"state-transition-race","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}