zeroclaw-labs/zeroclaw · critical
entry_hash mismatch at line {} (sequence {}): expected {}, g
Error message
entry_hash mismatch at line {} (sequence {}): expected {}, got {} What it means
The recomputed entry_hash (derived from the entry's prev_hash plus its contents via compute_entry_hash) differs from the entry_hash stored in the line. This means the entry's fields were modified after the record was written — content tampering detected, independent of chain linkage.
Source
Thrown at crates/zeroclaw-runtime/src/security/audit.rs:495
entry.sequence
);
}
// Check prev_hash linkage
if entry.prev_hash != expected_prev_hash {
bail!(
"prev_hash mismatch at line {} (sequence {}): expected {}, got {}",
line_idx + 1,
entry.sequence,
expected_prev_hash,
entry.prev_hash
);
}
// Recompute and verify entry_hash
let recomputed = compute_entry_hash(&entry.prev_hash, &entry);
if entry.entry_hash != recomputed {
bail!(
"entry_hash mismatch at line {} (sequence {}): expected {}, got {}",
line_idx + 1,
entry.sequence,
recomputed,
entry.entry_hash
);
}
// Verify signature if present and key is available
if let Some(ref signature) = entry.signature
&& let Some(ref key_bytes) = signing_key
{
use hmac::{Hmac, Mac};
use sha2::Sha256;
let mut mac = Hmac::<Sha256>::new_from_slice(key_bytes).map_err(|e| {
::zeroclaw_log::record!(
ERROR,View on GitHub (pinned to 88bb9c8533)
Solutions
- Restore the tampered line (or the whole file) from a trusted backup or off-site copy.
- Preserve the tampered file for forensics — the mismatch itself is the evidence.
- Audit who had write access to the log and tighten permissions (the writer should be the only writer).
- Never rewrite audit logs in place; if redaction is required, do it in a derived copy with a documented transform.
Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = audit.verify_chain() {
if e.to_string().contains("entry_hash mismatch") {
// content tampering: preserve the file byte-for-byte for forensics and alert
}
} Prevention
- Make audit logs append-only at the OS level where feasible.
- Never edit, redact, or reformat audit lines in place; derive views instead.
- Include hash-chain verification in log-shipping pipelines (verify before ship, verify after land).
When it happens
Trigger: Editing a field of an audit line (tool name, outcome, timestamp) with a text editor; sed/regex fixes across the log; a buggy script rewriting lines with serde re-serialization that changes field formatting; memory/disk corruption flipping bytes.
Common situations: Operators 'correcting' wrong-looking audit entries; automated redaction scripts that mutate the log in place; partial restores mixing old content with new hashes.
Related errors
- sequence gap at line {}: expected {}, got {}
- prev_hash mismatch at line {} (sequence {}): expected {}, go
- signature verification failed at line {} (sequence {}): sign
- purge_namespace not supported by this memory backend
- purge_session not supported by this memory backend
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/5ae5700dc7ce08e3.
Report an issue: GitHub.