tinyhumansai/openhuman · error · anyhow::Error

`{command}` was not found on OpenHuman's PATH. Install it (o

Error message

`{command}` was not found on OpenHuman's PATH. Install it (or its runtime) and make sure it's available in your shell, then restart OpenHuman.

What it means

The generic arm of the same pre-spawn guard: `locate_command` could not find the configured stdio command (any basename that is not npx/npm/node/uvx/uv) on the resolved PATH — config `env` PATH override if present, else OpenHuman's spawn PATH, searched relative to the server's `cwd` when set. The server process is never spawned; a `[mcp_client::stdio]` warn log records the command name.

Source

Thrown at src/openhuman/mcp/config_servers/stdio.rs:101

            command.env(key, value);
        }

        // Resolve the command up front so a missing Node/uv runtime fails with
        // actionable guidance instead of a bare ENOENT from `spawn`.
        let effective_path = self
            .env
            .iter()
            .rev()
            .find(|(key, _)| key == "PATH")
            .map(|(_, value)| value.as_str())
            .unwrap_or(resolved_path.as_str());
        if spawn_env::locate_command(&self.command, effective_path, self.cwd.as_deref()).is_none() {
            tracing::warn!(
                target: "[mcp_client::stdio]",
                command = %self.command,
                "stdio MCP command not found on resolved PATH"
            );
            anyhow::bail!(spawn_env::missing_command_error(&self.command));
        }

        let mut child = command
            .spawn()
            .with_context(|| format!("spawning MCP stdio server `{}`", self.command))?;
        let stdin = child
            .stdin
            .take()
            .ok_or_else(|| anyhow::anyhow!("stdio server missing stdin"))?;
        let stdout = child
            .stdout
            .take()
            .ok_or_else(|| anyhow::anyhow!("stdio server missing stdout"))?;
        let mut session = StdioSession {
            child,
            stdin,
            stdout: BufReader::new(stdout),
            initialize: McpInitializeResult {

View on GitHub (pinned to 7491200858)

Solutions

  1. Install the missing binary/runtime and restart OpenHuman so the new PATH is picked up.
  2. Set an explicit `env = { PATH = "..." }` on the server entry pointing at the binary's directory.
  3. Use an absolute `command` path (checked against cwd if set).
  4. Confirm the binary is executable and not a shell alias/function, which `locate_command` cannot see.

Example fix

# before
[[mcp_client.servers.custom]]
command = "my-mcp-bridge"

# after
[[mcp_client.servers.custom]]
command = "/usr/local/bin/my-mcp-bridge"
Defensive patterns

Strategy: validation

Validate before calling

let path = std::env::var("PATH").unwrap_or_default();
if spawn_env::locate_command(&server.command, &path, server.cwd.as_deref()).is_none() {
    // fail config validation early with the command name
}

Prevention

When it happens

Trigger: stdio server entries whose `command` is a custom binary, `docker`, `python`, `deno`, `bun`, etc., where the binary is absent, not executable, or only on the interactive shell's PATH.

Common situations: Dockerized/container deployments missing a runtime the config assumes; GUI launch losing shell PATH additions; script or binary installed after OpenHuman started (env is snapshotted at launch — the message explicitly says restart); command typo.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/ca1ecc973756fdc7. Report an issue: GitHub.