jdx/mise · error

no usable completion for

Error message

no usable {shell} completion for {}: {}

What it means

mise's packslip backend tries each registered completion source for a shell and collects every failure. When none yield a script, `completion_script` gives up with this error listing each source's failure reason. It means the tool's packslip manifest offers no completion script mise can render for that shell.

Solutions

  1. Check which shells the tool's packslip publishes and request one it ships (`mise completion bash --tool <tool>`)
  2. Verify network access / proxy settings so the completion assets can download
  3. Run with MISE_DEBUG=1 to see each skipped source's underlying error and address it (404, checksum, parse failure)
  4. Generate completions with the tool itself and install them manually (e.g. `<tool> completions bash > ...`), or file an issue upstream for missing shell support

Example fix

// before
mise completion fish --tool some-tool   # no usable fish completion
// after
mise completion bash --tool some-tool   # shell the packslip actually ships
Defensive patterns

Strategy: fallback

Validate before calling

mise completion bash --tool <tool> --dry-run 2>/dev/null || echo 'no completions for this shell'

Try / catch

match mise::packslip::completion_script(shell, tv) {
    Ok(script) => install(script),
    Err(e) => fallback_to_native_completions(tool, shell, e),
}

Prevention

When it happens

Trigger: Running `mise completion <shell> --tool <tool>` (or an install flow that fetches completions) for a packslip-installed tool where every candidate source errored — e.g. the manifest references a completion file that failed to download or a shell variant the manifest doesn't ship.

Common situations: Requesting completions for a shell the vendor doesn't publish (e.g. fish when only bash/zsh are shipped); offline or proxy-blocked downloads of completion assets; a malformed or stale packslip manifest pointing at missing assets.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/06886a80a9b7fe15. Report an issue: GitHub.

Appendix: source

Thrown at src/packslip.rs:1572

            }
        };
        match attempt {
            Ok(script) if script.trim().is_empty() => {
                skipped.push("nothing was printed".to_string())
            }
            Ok(script) => {
                if ran_tool
                    && let Some(dir) = cache.parent()
                    && file::create_dir_all(dir).is_ok()
                {
                    let _ = file::write_atomic(&cache, &script);
                }
                return Ok(script);
            }
            Err(err) => skipped.push(err.to_string()),
        }
    }
    bail!(
        "no usable {shell} completion for {}: {}",
        tv.style(),
        skipped.join("; ")
    )
}

/// Take turns generating, so that of the shells completing one command at
/// once the first runs the tool and the rest read what it cached. The lock
/// lives beside the cache, shared by every process that shares the install,
/// and is taken off the runtime's threads.
///
/// A read-only install cannot be locked and does not need to be: nothing
/// will be cached there either, so each shell generates its own script
/// rather than being refused a completion.
async fn lock_generation(cache: &Path) -> Option<fslock::LockFile> {
    let lock_path = cache.with_extension("lock");
    let taken = tokio::task::spawn_blocking(move || -> Result<fslock::LockFile> {
        if let Some(dir) = lock_path.parent() {

View on GitHub (pinned to 533346cc37)