Hmbown/CodeWhale · error · anyhow::Error

installed dsh is incompatible

Error message

installed dsh is incompatible: {reason}

What it means

launch_spec refuses to build a dsh launch when the integration state is Incompatible. The installed dsh client binary fails a compatibility check (e.g. its reported version or capabilities do not match what Codewhale's DSH integration expects), so launching would produce undefined behavior. The error carries the specific `reason` from the detection/status layer.

Solutions

  1. Read the `{reason}` in the message and install a dsh version compatible with this Codewhale build (see the version constraints in the DSH integration docs).
  2. Run `codewhale dsh status` to re-detect and confirm the current state and reported dsh version.
  3. Reinstall dsh via the documented channel (e.g. the install command Codewhale recommends), then re-run `codewhale dsh connect` if needed.
  4. Upgrade Codewhale itself if a newer dsh is intentionally installed and the incompatibility is a version-skew on Codewhale's side.

Example fix

// before: launching with an incompatible dsh on PATH
$ codewhale launch
Error: installed dsh is incompatible: dsh 0.4.0 < required 0.5.0

// after: pin a compatible dsh
$ dsh --version && npm i -g dsh@0.5
$ codewhale dsh status   # should no longer report Incompatible
$ codewhale launch
Defensive patterns

Strategy: validation

Validate before calling

let status = codewhale_dsh_status()?;
if matches!(status.state, DshIntegrationState::Incompatible { .. }) {
    eprintln!("dsh incompatible; upgrade dsh before launching");
    return Err(...);
}
launch_spec(&status, profile_override, extra_args, workspace)?;

Type guard

fn is_launchable(state: &DshIntegrationState) -> bool {
    matches!(state, DshIntegrationState::Connected { .. } | DshIntegrationState::StaleVersion { .. })
}

Try / catch

match launch_spec(&report, None, &[], &ws) {
    Err(e) if e.to_string().starts_with("installed dsh is incompatible") => {
        prompt_dsh_upgrade(&report.state);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `codewhale launch` (or any command that goes through dsh::launch_spec) after `dsh status`/detection classified the integration as DshIntegrationState::Incompatible — typically because the installed dsh version is too old, too new, or built with unexpected capabilities.

Common situations: dsh was upgraded or downgraded outside Codewhale; a distro-package or npm-global install replaced a version Codewhale pinned; a beta/nightly dsh build reports a version string the integration cannot parse or accept.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/6c88cb890c7baa50. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/integrations/dsh/mod.rs:694

) -> Result<LaunchSpec> {
    let record = report.record.as_ref().ok_or_else(|| {
        anyhow::anyhow!("DSH is not connected; run `{CLI_COMMAND} connect` first")
    })?;
    if !report.state.launchable() {
        match &report.state {
            DshIntegrationState::Connected { .. } | DshIntegrationState::StaleVersion { .. } => {}
            DshIntegrationState::Disabled { .. } => {
                anyhow::bail!(
                    "DSH integration is disabled; run `{CLI_COMMAND} enable` to launch again"
                )
            }
            DshIntegrationState::StaleConfig { reason, .. } => {
                anyhow::bail!(
                    "DSH overlay is stale ({reason}); run `{CLI_COMMAND} update` before launching"
                )
            }
            DshIntegrationState::Incompatible { reason, .. } => {
                anyhow::bail!("installed dsh is incompatible: {reason}")
            }
            DshIntegrationState::Offline { reason } => anyhow::bail!("dsh is offline: {reason}"),
            DshIntegrationState::NotInstalled => anyhow::bail!("dsh is not installed"),
            DshIntegrationState::Detected { .. } => {
                anyhow::bail!("DSH is detected but not connected; run `{CLI_COMMAND} connect`")
            }
        }
    }
    let binary = report
        .detection
        .binary
        .clone()
        .ok_or_else(|| anyhow::anyhow!("dsh binary path is unknown"))?;
    let bundle_installed = record.bundle.is_some();
    let profile = profile_override.unwrap_or(if bundle_installed {
        bundle::BUNDLE_PROFILE
    } else {
        record.profile.as_str()

View on GitHub (pinned to 73e0f67d83)