denisidoro/navi · error · anyhow

navi was unable to call tldr. Make sure tldr is correctly in

Error message

navi was unable to call tldr.
Make sure tldr is correctly installed.

Note:
{VERSION_DISCLAIMER}

What it means

`clients::tldr::call` spawns a `tldr` client to fetch a tldr page. If the client binary cannot be spawned, navi returns an error noting that tldr must be installed, plus a VERSION_DISCLAIMER about which tldr clients/flags navi supports (the --markdown flag).

Source

Thrown at src/clients/tldr.rs:78

    let child = Command::new("tldr")
        .args(args)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn();

    let child = match child {
        Ok(x) => x,
        Err(_) => {
            let msg = format!(
                "navi was unable to call tldr.
Make sure tldr is correctly installed.

Note:
{VERSION_DISCLAIMER}
"
            );
            return Err(anyhow!(msg));
        }
    };

    let out = child.wait_with_output().context("Failed to wait for tldr")?;

    if let Some(0) = out.status.code() {
        let stdout = out.stdout;

        let markdown = String::from_utf8(stdout).context("Output is invalid utf8")?;
        let lines = markdown_lines(query, &markdown);
        Ok(lines)
    } else {
        let msg = format!(
            "Failed to call:
tldr {}

Output:
{}

View on GitHub (pinned to f7330b9ad5)

Solutions

  1. Install a tldr client (npm install -g tldr, or cargo install tealdeer)
  2. Ensure the binary is named/linked as `tldr` and on PATH (`which tldr`)
  3. If using tealdeer, set the client.tealdeer config option in navi and ensure it supports the needed flags
  4. Use a different cheatsheet source (local dir or cheat.sh) instead

Example fix

// before
$ navi tldr tar
Error: navi was unable to call tldr.
// after
$ cargo install tealdeer && tldr --update
$ which tldr
~/.cargo/bin/tldr
$ navi tldr tar
Defensive patterns

Strategy: validation

Validate before calling

use std::process::Command;
fn tldr_available() -> bool {
    Command::new("tldr").arg("--version").output()
        .map(|o| o.status.success()).unwrap_or(false)
}
if !tldr_available() {
    eprintln!("install a tldr client (tealdeer or tldr npm package)");
    std::process::exit(1);
}

Try / catch

match tldr::call(query, opts) {
    Ok(lines) => render(lines),
    Err(e) if e.to_string().contains("unable to call tldr") => {
        eprintln!("tldr client missing: install tealdeer or tldr and ensure it's on PATH");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: `Command::new("tldr")...spawn()` fails: no tldr client installed (tldr node client, tealdeer, etc.), binary not on PATH, or not executable.

Common situations: Minimal installs without any tldr client, users who installed tealdeer as `tealdeer` but not aliased/symlinked as `tldr`, PATH issues in non-interactive shells.

Related errors


AI-assisted analysis of denisidoro/navi@f7330b9ad5 (2026-09-03). Data as JSON: /api/errors/f19abc030606fab8. Report an issue: GitHub.