Hmbown/CodeWhale · error

dsh binary is unknown

Error message

dsh binary is unknown

What it means

`install_into_profile` needs the dsh binary to run `dsh plugin --profile codewhale add <path>`; this guard fires when `detection.binary` is None — detection recorded no dsh executable. It mirrors the CLI-level guard (cli.rs:400) one layer down, protecting programmatic callers of the bundle installer from a detection report that never carried a binary.

Source

Thrown at crates/tui/src/integrations/dsh/bundle.rs:329

        args: args.iter().map(|s| (*s).to_string()).collect(),
        success,
        output_sha256: sha256_hex(output.as_bytes()),
        output_excerpt: excerpt.chars().take(400).collect(),
    })
}

/// Install the app bundle (linked from the installed launcher) and then the
/// Codewhale bundle, in that order so Codewhale's rows patch last.
pub(crate) fn install_into_profile(
    runner: &dyn DshRunner,
    detection: &DshDetection,
    app: DshAppBundle,
    bundle_dir: &Path,
) -> Result<(PathBuf, Vec<PluginCommandOutcome>)> {
    let binary = detection
        .binary
        .as_ref()
        .ok_or_else(|| anyhow::anyhow!("dsh binary is unknown"))?;
    let app_source = app_bundle_source(binary, app)?;
    let mut outcomes = Vec::new();
    let app_source_str = app_source.display().to_string();
    let first = run_dsh_plugin(runner, binary, BUNDLE_PROFILE, &["add", &app_source_str])?;
    let first_ok = first.success;
    let first_excerpt = first.output_excerpt.clone();
    outcomes.push(first);
    if !first_ok {
        anyhow::bail!(
            "dsh plugin add {} failed: {}",
            app.package_name(),
            first_excerpt
        );
    }
    let bundle_str = bundle_dir.display().to_string();
    let second = run_dsh_plugin(runner, binary, BUNDLE_PROFILE, &["add", &bundle_str])?;
    let second_ok = second.success;
    let second_excerpt = second.output_excerpt.clone();

View on GitHub (pinned to 8880682c63)

Solutions

  1. Ensure dsh is on PATH for the process running the install (`which dsh` must succeed)
  2. Reinstall dsh if it was removed: `npm i -g @deepseek-ai/dsh`
  3. Re-run detection fresh rather than reusing a stale report
  4. Run `codewhale integrations dsh status` first and require the `dsh binary:` line to show a path

Example fix

// before
let (dir, outcomes) = dsh::bundle::install_into_profile(runner, &detection, app, &bundle_dir)?;

// after — fail with intent before spawning anything
let binary = detection.binary.as_ref().ok_or_else(|| {
    anyhow::anyhow!("dsh binary is unknown; re-run detection with dsh on PATH")
})?;
let (dir, outcomes) = dsh::bundle::install_into_profile(runner, &detection, app, &bundle_dir)?;
Defensive patterns

Strategy: validation

Validate before calling

if detection.binary.is_none() {
    eprintln!("re-run detection with dsh on PATH before installing bundles");
    return Ok(());
}

Type guard

fn detection_has_binary(detection: &dsh::DshDetection) -> bool {
    detection.binary.is_some()
}

Prevention

When it happens

Trigger: Calling `dsh::bundle::install_into_profile` (as install-bundle does after its own checks) with a `DshDetection` whose binary field is None — dsh missing from PATH in the invoking environment, or a detection report built in a different (stripped) environment such as sudo, cron, or a service context.

Common situations: Automation invoking Codewhale under a minimal environment where PATH lacks the npm global bin; uninstalling dsh between status detection and the install step; constructing DshDetection from cached/stale data.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/9c56c6d77ac9e3af. Report an issue: GitHub.