{"record":{"id":"09002e8a1a90bfe3","repo":"nikivdev/code","slug":"unhash-output-missing-hash","errorCode":null,"errorMessage":"unhash output missing hash","messagePattern":"unhash output missing hash","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/hash.rs","lineNumber":40,"sourceCode":"\n    if env::var(\"UNHASH_KEY\").is_err() {\n        if let Ok(Some(value)) = flow_env::get_personal_env_var(\"UNHASH_KEY\") {\n            cmd.env(\"UNHASH_KEY\", value);\n        }\n    }\n\n    let output = cmd.output().context(\"failed to run unhash\")?;\n    if !output.status.success() {\n        let stdout = String::from_utf8_lossy(&output.stdout);\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        bail!(\"unhash failed: {}\\n{}{}\", output.status, stdout, stderr);\n    }\n\n    let stdout = String::from_utf8_lossy(&output.stdout);\n    let mut lines = stdout.lines().filter(|line| !line.trim().is_empty());\n    let hash = lines\n        .next()\n        .ok_or_else(|| anyhow::anyhow!(\"unhash output missing hash\"))?\n        .trim()\n        .to_string();\n\n    let link = format!(\"{LINK_PREFIX}{hash}\");\n    copy_to_clipboard(&link)?;\n\n    println!(\"{hash}\");\n    println!(\"{link}\");\n\n    if let Some(path_line) = lines.next() {\n        println!(\"{}\", path_line.trim());\n    }\n\n    Ok(())\n}\n\nfn copy_to_clipboard(text: &str) -> Result<()> {\n    if std::env::var(\"FLOW_NO_CLIPBOARD\").is_ok() || !std::io::stdin().is_terminal() {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/hash.rs#L22-L58","documentation":"run computes a hash via an external command (unhash/hash tool), reads the first non-empty stdout line, and throws this error when the output has no lines at all. It protects the LINK_PREFIX link construction from an empty hash.","triggerScenarios":"The underlying hash command exits with empty stdout (failed silently, wrong subcommand, empty input) so lines.next() is None.","commonSituations":"Hash tool not installed or returning empty due to error on stderr, piping empty input, version change that renamed the output field.","solutions":["Check the command's stderr/exit status and surface it instead of stdout alone","Verify the hash tool is installed and on PATH and produces output for your input","Ensure you pass non-empty input to hash"],"exampleFix":"// before\nlet hash = lines.next().ok_or_else(|| anyhow::anyhow!(\"unhash output missing hash\"))?;\n// after\nif !output.status.success() {\n    anyhow::bail!(\"hash command failed: {}\", String::from_utf8_lossy(&output.stderr));\n}\nlet hash = lines.next().ok_or_else(|| anyhow::anyhow!(\"unhash output missing hash\"))?;","handlingStrategy":"try-catch","validationCode":"let out = Command::new(\"f\").args([\"hash\", input]).output()?;\nif !out.status.success() || out.stdout.iter().all(|&b| b.is_ascii_whitespace()) {\n    anyhow::bail!(\"hash tool produced no output: {}\", String::from_utf8_lossy(&out.stderr));\n}","typeGuard":null,"tryCatchPattern":"match run(input) {\n    Err(e) if e.to_string().contains(\"missing hash\") => {\n        eprintln!(\"hash tool returned empty output; check stderr of the hash command\");\n    }\n    other => other?,\n}","preventionTips":["Check exit status/stderr of external commands, not just stdout","Pin/verify the hash tool version your parser expects","Never pipe empty input into hash"],"tags":["external-command","parsing","empty-output"],"backgroundTag":"unexpected-empty-output","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}