Hmbown/CodeWhale · error · anyhow::Error
unknown runtime backend `{other}` (use tmux|inline|vm|ci)
Error message
unknown runtime backend `{other}` (use tmux|inline|vm|ci) What it means
Thrown by RuntimeBackend::parse when the backend string, after trimming and lowercasing, is not one of the four supported backends: tmux, inline, vm, or ci. Parsing is case-insensitive and whitespace-tolerant, so the failure means the value is genuinely a different word (e.g. 'docker', 'ssh', 'local') or a typo.
Source
Thrown at crates/lane/src/runtime.rs:44
}
impl RuntimeBackendKind {
pub fn as_str(self) -> &'static str {
match self {
Self::Tmux => "tmux",
Self::Inline => "inline",
Self::Vm => "vm",
Self::Ci => "ci",
}
}
pub fn parse(raw: &str) -> Result<Self> {
match raw.trim().to_ascii_lowercase().as_str() {
"tmux" => Ok(Self::Tmux),
"inline" => Ok(Self::Inline),
"vm" => Ok(Self::Vm),
"ci" => Ok(Self::Ci),
other => bail!("unknown runtime backend `{other}` (use tmux|inline|vm|ci)"),
}
}
}
/// Inputs for starting a lane under a runtime backend.
#[derive(Clone)]
pub struct LaneStartSpec {
/// Command argv to run inside the backend (e.g. `codewhale exec …`).
pub command: Vec<String>,
/// Working directory for the command (defaults to worktree or cwd).
pub cwd: Option<PathBuf>,
/// Process-local runtime overrides. Values are never written into the
/// Lane record or command argv; tmux bridges them through a private 0600
/// environment file that the detached shell removes before execution.
pub environment: Vec<(String, String)>,
/// Executable that exposes Codewhale's hidden `lane-log-proxy` command.
/// Required by tmux so arbitrary/binary child output is framed as valid
/// NDJSON without trusting a shell pipeline.View on GitHub (pinned to 0c42157ee5)
Solutions
- Use one of the four supported values: tmux, inline, vm, or ci (case-insensitive)
- Check for typos and stray characters — 'in line' with a space or 'vm:' with a suffix both fail
- If you need a container/remote feel today, map it onto 'vm' or 'ci' as documented, or remove the setting to use the default backend
Example fix
# before runtime = "docker" # after runtime = "vm"
Defensive patterns
Strategy: type-guard
Validate before calling
fn valid_backend(raw: &str) -> bool {
matches!(raw.trim().to_ascii_lowercase().as_str(), "tmux" | "inline" | "vm" | "ci")
}
assert!(valid_backend(&raw), "runtime must be one of tmux|inline|vm|ci"); Type guard
fn is_supported_backend(raw: &str) -> bool {
matches!(raw.trim().to_ascii_lowercase().as_str(), "tmux" | "inline" | "vm" | "ci")
} Try / catch
let backend = match RuntimeBackend::parse(&raw) {
Ok(b) => b,
Err(err) if err.to_string().contains("unknown runtime backend") => {
RuntimeBackend::parse("tmux")? // explicit fallback to default backend
}
Err(err) => return Err(err),
}; Prevention
- Offer backend as a closed-choice option (CLI enum/config dropdown), never free text
- Reject unknown backend strings at config load with the supported list in the message
When it happens
Trigger: A runtime = "docker" or "remote" entry in lane/runtime config, a CLI flag like --runtime ssh, or a typo such as "in line" or "tmux2". Only the exact four identifiers (in any case) parse.
Common situations: Assuming a Docker/SSH backend exists because other agent tools have one; config copied between tool versions where backend names changed; machine-generated configs enumerating hypothetical backends.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- project workspace path cannot be empty
- terminal lane transition requires a terminal status
- invalid lane environment key {key:?}
- private lane environment exceeds {} bytes
- serialized lane exit receipt exceeds size bound
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/e10cebf09ded608d.
Report an issue: GitHub.