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

  1. Provide a non-empty command in the `LaneStartSpec` or on the CLI invocation.
  2. Add validation at your config/CLI boundary that rejects blank command values with a clear message naming the field.
  3. 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

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


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)