{"record":{"id":"327cac93b0dd1d8f","repo":"Hmbown/CodeWhale","slug":"lane-was-stopped-before-tmux-dry-run-start-co","errorCode":null,"errorMessage":"lane `{}` was stopped before tmux dry-run start completed","messagePattern":"lane `(.+?)` was stopped before tmux dry-run start completed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/lane/src/runtime.rs","lineNumber":729,"sourceCode":"                \"workflow\": record.workflow,\n                \"fleet\": record.fleet,\n                \"issue\": record.issue,\n                \"dry_run\": dry_run,\n            }),\n        )?;\n\n        if dry_run {\n            append_log_event(\n                &record.log_path,\n                serde_json::json!({\n                    \"type\": \"lane_log\",\n                    \"message\": \"tmux dry-run: session recorded without spawning process\",\n                    \"command\": spec.command,\n                    \"cwd\": cwd.as_ref().map(|p| p.display().to_string()),\n                }),\n            )?;\n            if !registry.mark_running_if_pending(record)? {\n                bail!(\n                    \"lane `{}` was stopped before tmux dry-run start completed\",\n                    record.id\n                );\n            }\n            return Ok(());\n        }\n\n        let log_proxy = spec\n            .log_proxy\n            .as_deref()\n            .context(\"tmux runtime requires a lane log proxy executable\")?;\n\n        // Detached session: child output remains an operator journal only.\n        // Terminal control state goes through a separate bounded, atomically\n        // renamed receipt so child stdout cannot forge Lane completion.\n        let receipt_path = lane_exit_receipt_path(&record.log_path);\n        let receipt_tmp_path = lane_exit_receipt_tmp_path(&record.log_path);\n        let environment_path = lane_environment_path(&record.log_path);","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/lane/src/runtime.rs#L711-L747","documentation":"In the CODEWHALE_LANE_TMUX_DRY_RUN test path, TmuxRuntime::start records a lane_log event and then calls registry.mark_running_if_pending(record). A false return means the lane's status is no longer Pending — a concurrent stop already claimed it — so the start aborts rather than flipping a stopped lane back to Running.","triggerScenarios":"Dry-run lane start racing a concurrent stop (or a registry transition) on the same lane id: by the time the Pending->Running compare-and-set runs, the state has moved. Only occurs with CODEWHALE_LANE_TMUX_DRY_RUN set, i.e. in tests.","commonSituations":"Parallel tests starting and stopping the same lane id; test code issuing stop immediately after start without waiting for the transition; shared registry state across test tasks.","solutions":["Treat the lane as stopped: refetch its record and assert the terminal state instead of retrying the start","Serialize start/stop per lane id in tests (await the start's completion before stopping)","Use distinct lane ids per test to avoid registry contention"],"exampleFix":"// before\nstart(lane_id);\nstop(lane_id); // may win the race in dry-run tests\n\n// after\nstart(lane_id).await?; // wait for the Pending->Running transition\nstop(lane_id).await?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match runtime.start(&registry, &mut record, &spec) {\n    Ok(()) => { /* lane running (dry-run recorded) */ }\n    Err(err) if err.to_string().contains(\"stopped before\") => {\n        let fresh = registry.get(&lane_id)?; // refetch: lane is stopped, not failed\n        assert_eq!(fresh.status, LaneStatus::Stopped);\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Await start completion before issuing stop in tests","Use unique lane ids per test to avoid registry contention","Treat 'stopped before ...' errors as races, not resource failures — never blind-retry"],"tags":["rust","lane","tmux","dry-run","race-condition","testing"],"backgroundTag":"state-transition-race","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}