nikivdev/code · error

unhash failed: {} {}{}

Error message

unhash failed: {}
{}{}

What it means

`f hash` delegates to the external `unhash` binary. If `unhash` exits with a non-zero status, the command bails with this message, embedding the exit status plus unhash's stdout and stderr so the underlying failure is visible. This is the error path for any failure inside unhash itself, not for the wrapper's own setup.

Source

Thrown at src/hash.rs:33

    }

    let unhash_bin = which::which("unhash")
        .context("unhash not found on PATH. Run `f deploy-unhash` in the unhash repo.")?;

    let mut cmd = Command::new(unhash_bin);
    cmd.args(&opts.args);

    if env::var("UNHASH_KEY").is_err() {
        if let Ok(Some(value)) = flow_env::get_personal_env_var("UNHASH_KEY") {
            cmd.env("UNHASH_KEY", value);
        }
    }

    let output = cmd.output().context("failed to run unhash")?;
    if !output.status.success() {
        let stdout = String::from_utf8_lossy(&output.stdout);
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!("unhash failed: {}\n{}{}", output.status, stdout, stderr);
    }

    let stdout = String::from_utf8_lossy(&output.stdout);
    let mut lines = stdout.lines().filter(|line| !line.trim().is_empty());
    let hash = lines
        .next()
        .ok_or_else(|| anyhow::anyhow!("unhash output missing hash"))?
        .trim()
        .to_string();

    let link = format!("{LINK_PREFIX}{hash}");
    copy_to_clipboard(&link)?;

    println!("{hash}");
    println!("{link}");

    if let Some(path_line) = lines.next() {
        println!("{}", path_line.trim());

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the stdout/stderr embedded in the error message — it contains unhash's own diagnosis
  2. Verify the target paths exist and are readable before hashing
  3. Run `unhash` directly with the same arguments to reproduce outside the wrapper
  4. Reinstall or update unhash: `f deploy-unhash` in the unhash repo

Example fix

# before (opaque invocation)
 f hash "unstash./abc123"
# after (inspect actual args/path first)
ls -l <path> && unhash <path>   # reproduce directly, then fix the path or entry
Defensive patterns

Strategy: try-catch

Validate before calling

let unhash = which::which("unhash")?;
for p in &paths {
    anyhow::ensure!(p.exists(), "path does not exist: {}", p.display());
    anyhow::ensure!(p.is_readable(), "path not readable: {}", p.display());
}

Type guard

null

Try / catch

match hash::run(opts) {
    Err(e) if e.to_string().starts_with("unhash failed:") => {
        // stderr/stdout of unhash are embedded; forward them verbatim
        eprintln!("{e}");
        std::process::exit(1);
    }
    r => r?,
}

Prevention

When it happens

Trigger: unhash encountering a missing/permission-denied input path; unhash failing to parse its arguments as forwarded by the wrapper; unhash's own internal errors (corrupt hash DB, network backend failure for unstash operations); disk full while unhash writes output.

Common situations: Hashing a path that was deleted or renamed between listing and hashing; passing flags unhash doesn't recognize; unhash's data directory corrupted or not initialized; `unstash./` arguments referencing entries that don't exist.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/50df69fe4bac0374. Report an issue: GitHub.