{"record":{"id":"98f80228eb82baeb","repo":"rtk-ai/rtk","slug":"invalid-hash-format-in-expected-hash-filenam","errorCode":null,"errorMessage":"Invalid hash format in {} (expected 'hash  filename')","messagePattern":"Invalid hash format in (.+?) \\(expected 'hash  filename'\\)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/hooks/integrity.rs","lineNumber":182,"sourceCode":"}\n\n/// Read the stored hash from the hash file.\n///\n/// Expects exact `sha256sum -c` format: `<64 hex>  <filename>\\n`\n/// Rejects malformed files rather than silently accepting them.\nfn read_stored_hash(path: &Path) -> Result<String> {\n    let content = fs::read_to_string(path)\n        .with_context(|| format!(\"Failed to read hash file: {}\", path.display()))?;\n\n    let line = content\n        .lines()\n        .next()\n        .with_context(|| format!(\"Empty hash file: {}\", path.display()))?;\n\n    // sha256sum format uses two-space separator: \"<hash>  <filename>\"\n    let parts: Vec<&str> = line.splitn(2, \"  \").collect();\n    if parts.len() != 2 {\n        anyhow::bail!(\n            \"Invalid hash format in {} (expected 'hash  filename')\",\n            path.display()\n        );\n    }\n\n    let hash = parts[0];\n    if hash.len() != 64 || !hash.chars().all(|c| c.is_ascii_hexdigit()) {\n        anyhow::bail!(\"Invalid SHA-256 hash in {}\", path.display());\n    }\n\n    Ok(hash.to_string())\n}\n\n/// Resolve the default hook path (~/.claude/hooks/rtk-rewrite.sh)\npub fn resolve_hook_path() -> Result<PathBuf> {\n    resolve_claude_dir().map(|dir| dir.join(HOOKS_SUBDIR).join(REWRITE_HOOK_FILE))\n}\n","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/rtk-ai/rtk/blob/d977e1c31621fe8704e6500ceeb9c7a0de2b6836/src/hooks/integrity.rs#L164-L200","documentation":"rtk verify stores the rewrite hook's digest in sha256sum layout: '<64 hex chars>  <filename>' with a two-space separator. read_stored_hash splits the first line on '  ' and bails when the split yields only one field, i.e. the .sha256 sidecar file is not in sha256sum format at all.","triggerScenarios":"The hook's .sha256 sidecar (e.g. ~/.claude/hooks/rtk-rewrite.sh.sha256) was hand-edited, reformatted by a dotfile manager, or generated by a tool using a single space or a different layout; the next `rtk verify` fails at src/hooks/integrity.rs:184.","commonSituations":"chezmoi/stow templates rewriting hash files; CI regenerating hashes with `shasum` (macOS) or custom scripts; an empty or truncated file.","solutions":["Regenerate in canonical format: `sha256sum ~/.claude/hooks/rtk-rewrite.sh > ~/.claude/hooks/rtk-rewrite.sh.sha256`","Or re-run `rtk init -g` so rtk rewrites both the hook and its hash consistently","Check the first line matches `<64 hex chars><two spaces><filename>`"],"exampleFix":"# before: single-space or mangled layout\nabc123... single-space-name\n\n# after\nsha256sum ~/.claude/hooks/rtk-rewrite.sh > ~/.claude/hooks/rtk-rewrite.sh.sha256","handlingStrategy":"validation","validationCode":"# bash: pre-check the sha256sum sidecar layout before `rtk verify`\nSHA=~/.claude/hooks/rtk-rewrite.sh.sha256\nhead -1 \"$SHA\" | grep -qE '^[0-9a-fA-F]{64}  ' || { echo \"bad sha256sum layout in $SHA\" >&2; exit 2; }","typeGuard":"// Rust: true when a line is valid sha256sum layout ('<64 hex>  <filename>')\nfn is_sha256sum_line(line: &str) -> bool {\n    let mut parts = line.splitn(2, \"  \");\n    matches!(parts.next(), Some(h) if h.len() == 64 && h.chars().all(|c| c.is_ascii_hexdigit()))\n        && parts.next().is_some()\n}","tryCatchPattern":null,"preventionTips":["Generate hash files only with `sha256sum`, never shasum/md5sum or hand edits","Exclude rtk's .sha256 sidecars from dotfile templating that collapses whitespace","Prefer re-running `rtk init -g` over manually regenerating integrity files"],"tags":["integrity","sha256","verify","file-format"],"backgroundTag":null,"analyzedSha":"d977e1c31621fe8704e6500ceeb9c7a0de2b6836","analyzedAt":"2026-08-16T05:40:46.291Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}