{"record":{"id":"80fa1cbe0ef17a76","repo":"Hmbown/CodeWhale","slug":"inline-runtime-requires-a-non-empty-command","errorCode":null,"errorMessage":"inline runtime requires a non-empty command","messagePattern":"inline runtime requires a non-empty command","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/lane/src/runtime.rs","lineNumber":956,"sourceCode":"}\n\n/// In-process / local command runtime (no tmux). Used for tests and headless.\n#[derive(Debug, Default)]\npub struct InlineRuntime;\n\nimpl RuntimeBackend for InlineRuntime {\n    fn kind(&self) -> RuntimeBackendKind {\n        RuntimeBackendKind::Inline\n    }\n\n    fn start(\n        &self,\n        registry: &LaneRegistry,\n        record: &mut LaneRecord,\n        spec: &LaneStartSpec,\n    ) -> Result<()> {\n        if spec.command.is_empty() {\n            bail!(\"inline runtime requires a non-empty command\");\n        }\n        let cwd = apply_worktree(record, spec)?;\n        append_log_event(\n            &record.log_path,\n            serde_json::json!({\n                \"type\": \"lane_started\",\n                \"lane_id\": record.id,\n                \"runtime\": \"inline\",\n                \"command\": spec.command,\n            }),\n        )?;\n        if !registry.mark_running_if_pending(record)? {\n            bail!(\n                \"lane `{}` was stopped before inline start completed\",\n                record.id\n            );\n        }\n","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/lane/src/runtime.rs#L938-L974","documentation":"InlineRuntime::start rejects a LaneStartSpec with an empty command vector before creating a worktree or appending the lane_started event. The inline backend execs spec.command[0] directly as a child process, so an empty vector has no program to run and is refused at the boundary — no state is mutated.","triggerScenarios":"Calling lane start with backend \"inline\" and spec.command = [] — e.g. a blank command string split into words, or a defaulted empty vec from an options parser.","commonSituations":"Config files with empty command entries; CLI arguments consumed without values; commands derived from filtered/conditional lists that collapse to nothing.","solutions":["Supply a concrete program (e.g. [\"bash\", \"-c\", script] or [\"make\", \"test\"]) in the spec","Validate command non-emptiness in your own layer before building the spec","Fix the config entry that produced the blank command"],"exampleFix":"// before\nlet spec = LaneStartSpec { command: cmd_line.split(' ').map(String::from).collect(), .. }; // \"\" -> []\n\n// after\nlet command: Vec<String> = cmd_line\n    .split_whitespace()\n    .map(String::from)\n    .collect::<Vec<_>>();\nanyhow::ensure!(!command.is_empty(), \"lane command must not be empty\");\nlet spec = LaneStartSpec { command, .. };","handlingStrategy":"validation","validationCode":"anyhow::ensure!(!spec.command.is_empty(), \"lane command must not be empty\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate command presence where specs are constructed (config load, CLI parse)","Split command strings with split_whitespace so blank input never becomes a spec"],"tags":["rust","lane","inline","validation","empty-argument"],"backgroundTag":"empty-required-field","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}