zeroclaw-labs/zeroclaw · critical

prev_hash mismatch at line {} (sequence {}): expected {}, go

Error message

prev_hash mismatch at line {} (sequence {}): expected {}, got {}

What it means

An entry's prev_hash does not equal the previous entry's entry_hash, so the hash-chain linkage is broken at that line. The chain proves each record hash-seals its predecessor; a mismatch means lines were inserted, removed, or reordered after the fact — the log has been spliced or corrupted.

Source

Thrown at crates/zeroclaw-runtime/src/security/audit.rs:483

        let line = line?;
        if line.trim().is_empty() {
            continue;
        }
        let entry: AuditEvent = serde_json::from_str(&line)?;

        // Check sequence continuity
        if entry.sequence != expected_sequence {
            bail!(
                "sequence gap at line {}: expected {}, got {}",
                line_idx + 1,
                expected_sequence,
                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
            );

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Compare against the newest intact backup and restore it; quantify what changed since.
  2. Treat as a tamper event: quarantine the log, alert security, preserve the original file.
  3. If the cause is benign (merging logs), split back into the original per-daemon files and verify each separately.
  4. Prevent recurrence: single writer via endpoint lock, append-only permissions where possible.
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = audit.verify_chain() {
    if e.to_string().contains("prev_hash mismatch") {
        // splice/reorder detected: quarantine file, compare with last known-good backup, alert
    }
}

Prevention

When it happens

Trigger: A forged line inserted into the middle of the log; two log segments from different runs concatenated out of order; lines deleted and neighbors not resealing (they never re-seal, hence detection); manual reorder during 'cleanup'.

Common situations: Tamper-evidence tests; merging audit logs from two daemon instances by accident; restoring an interleaved backup; text-editor saves that reorder or drop lines.

Related errors


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