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

  1. Restore the tampered line (or the whole file) from a trusted backup or off-site copy.
  2. Preserve the tampered file for forensics — the mismatch itself is the evidence.
  3. Audit who had write access to the log and tighten permissions (the writer should be the only writer).
  4. 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

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


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/5ae5700dc7ce08e3. Report an issue: GitHub.