rtk-ai/rtk · error
Invalid SHA-256 hash in
Error message
Invalid SHA-256 hash in {} What it means
After splitting, read_stored_hash validates that the extracted hash field is exactly 64 ASCII hex characters (a real SHA-256 digest). If it is shorter/longer or contains non-hex characters, the stored checksum is unusable and the function bails to prevent a trivially-true or broken integrity comparison.
Solutions
- Regenerate with SHA-256: `sha256sum <hook file> > <hook file>.sha256` from within the hooks directory
- Verify the first field: `awk '{print length($1)}' <hook>.sha256` must print 64
- Reinstall via rtk init so the checksum is written by rtk itself
Example fix
// before (md5, 32 chars) md5sum rtk-rewrite.sh > rtk-rewrite.sh.sha256 // after (cd ~/.claude/hooks && sha256sum rtk-rewrite.sh > rtk-rewrite.sh.sha256)
Defensive patterns
Strategy: validation
Validate before calling
HASH=$(cut -d' ' -f1 "$hook.sha256"); [[ ${#HASH} -eq 64 && "$HASH" =~ ^[0-9a-fA-F]{64}$ ]] || sha256sum "$hook" > "$hook.sha256" Type guard
fn is_sha256_hex(s: &str) -> bool {
s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())
} Try / catch
match read_stored_hash(&hash_path) {
Err(e) if e.to_string().contains("Invalid SHA-256") => {
eprintln!("regenerating checksum for {}", hash_path.display());
write_checksum(&hook_path)?;
}
other => other?,
} Prevention
- Use sha256sum exclusively; md5 digests (32 hex) fail the length check
- Never truncate or placeholder-edit digests when scripting
- Reinstall hooks via rtk init rather than copying checksum files between machines
When it happens
Trigger: Calling verify_hook_at where the hash file contains a truncated hash, a placeholder like '<hash>', an md5 (32 hex chars) instead of sha256, or the filename was accidentally split into the hash field (single-space separator shifting fields).
Common situations: Regenerating checksums with `md5sum` instead of `sha256sum`; copy/paste truncating the digest; editing tools mangling the line; corruption of the checksum file on disk.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Invalid hash format in
- --codex cannot be combined with --auto-patch
- --codex cannot be combined with --claude-md
- --codex cannot be combined with --hook-only
- --codex cannot be combined with --no-patch
AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19).
Data as JSON: /api/errors/4587f6f2f8786fe4.
Report an issue: GitHub.
Appendix: source
Thrown at src/hooks/integrity.rs:190
.with_context(|| format!("Failed to read hash file: {}", path.display()))?;
let line = content
.lines()
.next()
.with_context(|| format!("Empty hash file: {}", path.display()))?;
// sha256sum format uses two-space separator: "<hash> <filename>"
let parts: Vec<&str> = line.splitn(2, " ").collect();
if parts.len() != 2 {
anyhow::bail!(
"Invalid hash format in {} (expected 'hash filename')",
path.display()
);
}
let hash = parts[0];
if hash.len() != 64 || !hash.chars().all(|c| c.is_ascii_hexdigit()) {
anyhow::bail!("Invalid SHA-256 hash in {}", path.display());
}
Ok(hash.to_string())
}
/// Resolve the default hook path (~/.claude/hooks/rtk-rewrite.sh)
pub fn resolve_hook_path() -> Result<PathBuf> {
resolve_claude_dir().map(|dir| dir.join(HOOKS_SUBDIR).join(REWRITE_HOOK_FILE))
}
/// Run integrity check and print results (for `rtk verify` subcommand)
pub fn run_verify(verbose: u8) -> Result<()> {
let result = report_hook_status(verbose);
report_data_dir_privacy();
result
}
fn report_hook_status(verbose: u8) -> Result<()> {View on GitHub (pinned to 0924356b4c)