{"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":null,"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/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/lane/src/runtime.rs#L938-L974","documentation":"The inline runtime's `start` validates that the lane start spec carries a non-empty command before applying the worktree or logging anything. Unlike the tmux runtime there is no session wrapper, so the command itself is the process; an empty command would spawn nothing or fail opaquely downstream, hence the upfront rejection.","triggerScenarios":"Calling `LaneRuntime::start` (inline runtime path) with a `LaneStartSpec` whose `command` is empty — omitted CLI command argument, a config field defaulting to an empty string, or programmatic spec construction leaving the field unset.","commonSituations":"`codewhale lane start` invoked without the command positional/flag; a YAML/JSON lane config with `command: \"\"`; a wrapper script passing `\"$CMD\"` where CMD is unset and expands to empty.","solutions":["Provide a non-empty command in the `LaneStartSpec` or on the CLI invocation.","Add validation at your config/CLI boundary that rejects blank command values with a clear message naming the field.","If the command is built from a template or environment variable, assert the interpolated value is non-empty before calling start."],"exampleFix":"// before (unexpanded env var)\nlet spec = LaneStartSpec { command: env_cmd.unwrap_or_default(), .. };\n\n// after\nlet cmd = env_cmd.ok_or_else(|| anyhow!(\"LANE_CMD must be set\"))?;\nlet spec = LaneStartSpec { command: cmd, .. };","handlingStrategy":"validation","validationCode":"if spec.command.is_empty() {\n    return Err(\"inline lane command must be non-empty\".into());\n}","typeGuard":"fn has_command(spec: &LaneStartSpec) -> bool { !spec.command.is_empty() }","tryCatchPattern":null,"preventionTips":["Require the command at the CLI/config layer so empty values are rejected early.","When sourcing commands from env vars/templates, assert non-emptiness after expansion.","Validate the whole LaneStartSpec once before dispatching to any runtime."],"tags":["validation","arguments","inline-runtime"],"backgroundTag":"empty-required-field","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"}