Hmbown/CodeWhale · error
inline runtime requires a non-empty command
Error message
inline runtime requires a non-empty command
What it means
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.
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.
Example fix
// before (unexpanded env var)
let spec = LaneStartSpec { command: env_cmd.unwrap_or_default(), .. };
// after
let cmd = env_cmd.ok_or_else(|| anyhow!("LANE_CMD must be set"))?;
let spec = LaneStartSpec { command: cmd, .. }; Defensive patterns
Strategy: validation
Validate before calling
if spec.command.is_empty() {
return Err("inline lane command must be non-empty".into());
} Type guard
fn has_command(spec: &LaneStartSpec) -> bool { !spec.command.is_empty() } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: `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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- --attempts must be an integer from 1 to 20
- --channel, --version and --reason are required
- Choose one Runtime --thread ID.
- click supports left with 1-3 clicks, right x1 or middle x1
- Command is required
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/80fa1cbe0ef17a76.
Report an issue: GitHub.
Appendix: source
Thrown at crates/lane/src/runtime.rs:956
}
/// In-process / local command runtime (no tmux). Used for tests and headless.
#[derive(Debug, Default)]
pub struct InlineRuntime;
impl RuntimeBackend for InlineRuntime {
fn kind(&self) -> RuntimeBackendKind {
RuntimeBackendKind::Inline
}
fn start(
&self,
registry: &LaneRegistry,
record: &mut LaneRecord,
spec: &LaneStartSpec,
) -> Result<()> {
if spec.command.is_empty() {
bail!("inline runtime requires a non-empty command");
}
let cwd = apply_worktree(record, spec)?;
append_log_event(
&record.log_path,
serde_json::json!({
"type": "lane_started",
"lane_id": record.id,
"runtime": "inline",
"command": spec.command,
}),
)?;
if !registry.mark_running_if_pending(record)? {
bail!(
"lane `{}` was stopped before inline start completed",
record.id
);
}
View on GitHub (pinned to 73e0f67d83)