tinyhumansai/openhuman · error · anyhow::Error

[claude-code] `claude` CLI at {} unusable: {}

Error message

[claude-code] `claude` CLI at {} unusable: {}

What it means

`version_check::probe()` located a `claude` binary but could not use it — the `CliStatus::Unusable` arm. The probe's `reason` (appended to the message) covers failures like the binary not being executable, spawning it failed, or its `--version` output being unparseable. Distinct from NotInstalled (nothing found) and Outdated (usable but too old).

Source

Thrown at src/openhuman/inference/provider/claude_code/mod.rs:152

            types::CliStatus::NotInstalled => {
                anyhow::bail!(
                    "[claude-code] `claude` CLI not installed. Install Claude Code CLI \
                     ({}) >= {} and retry.",
                    "https://docs.anthropic.com/en/docs/claude-code",
                    types::MIN_CLI_VERSION
                )
            }
            types::CliStatus::Outdated {
                version,
                min_required,
                path,
            } => anyhow::bail!(
                "[claude-code] `claude` CLI at {} is version {}; require >= {}",
                path,
                version,
                min_required
            ),
            types::CliStatus::Unusable { path, reason } => anyhow::bail!(
                "[claude-code] `claude` CLI at {} unusable: {}",
                path,
                reason
            ),
        }
    }

    async fn run_chat(
        &self,
        request: ChatRequest<'_>,
        model_override: Option<&str>,
    ) -> anyhow::Result<ChatResponse> {
        // Cap concurrent CC processes.
        let _permit = self
            .semaphore
            .clone()
            .acquire_owned()
            .await

View on GitHub (pinned to 7491200858)

Solutions

  1. Read the `reason` in the message — it names the exact probe failure.
  2. Run `<path> --version` manually in a shell; if it errors or prints anything besides a version, fix or reinstall at that path.
  3. Reinstall the CLI cleanly (`npm uninstall -g @anthropic-ai/claude-code && npm install -g @anthropic-ai/claude-code`) to replace broken shims.
  4. If a wrapper (nvm/asdf) is the culprit, point PATH directly at a real Node bin dir containing a working `claude`.

Example fix

# diagnose at the exact path from the message
/path/to/claude --version || echo "binary broken -> reinstall"
npm uninstall -g @anthropic-ai/claude-code && npm install -g @anthropic-ai/claude-code
Defensive patterns

Strategy: validation

Validate before calling

if let types::CliStatus::Unusable { path, reason } = version_check::probe() {
    log::warn!("claude CLI unusable at {path}: {reason}");
    return use_fallback_provider();
}

Prevention

When it happens

Trigger: A `claude` file exists on PATH but: lacks the executable bit, is a broken symlink/shim (half-failed npm install), is a shell script whose interpreter is missing, or prints version output the parser cannot read (locale-mangled, wrapper banners prepended).

Common situations: Interrupted npm installs leaving a dead shim; wrapper scripts (nvm/asdf shims) whose backing runtime was removed; permissions broken after a backup/copy; custom wrapper scripts prepending text to CLI output.

Related errors


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