Repository navigation
fix(wal): never append after a torn WAL entry (#513) - #514
Merged
Merged
Conversation
WAL replay stops at the first partial or damaged entry, but the writer appended at the end of the file. After a crash during an append, the next session's commits went in after the partial entry, so a second crash before any checkpoint lost them although each was fsynced and reported committed. A failed append in a running process did the same to the next commit through that handle. - WalWriter::open_or_create_at cuts an existing WAL back to the end of its last valid entry and syncs it before appending (scan_entries, shared with WalReader::read_entries). - After a failed write or sync, the writer refuses every later append with the new WAL-007. A checkpoint (which deletes the WAL) or a reopen starts a clean writer. A rejected oversize fact (WAL-003) writes nothing and does not poison the writer. Tests: WAL unit tests for each torn-tail shape, a bad-checksum entry, an intact WAL left byte for byte, WAL-007 after a torn append (test-only hook), and WAL-003 not poisoning; a Minigraf test for WAL-007 from transact and commit and recovery by checkpoint; and a wal_test.rs integration test that crashes a child after a torn tail and checks the commit survives. Refs #513 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012wXxZguv7PgKQjMMH4yJ5h
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced Oct 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #513 (data-integrity: stays open until the fix is in a published release). Found while working on #390.
Problem
WAL replay stops at the first partial or damaged entry, but
WalWriterappended at the end of the file. After a crash during an append, the next session's commits went in after the partial entry, so a second crash before any checkpoint lost them, although each was fsynced and reported committed. A failed append (short write, ENOSPC, EIO) in a running process did the same to the next commit through that handle. Reproduced onv3and onmain(v2.0.4).Fix
WalWriter::open_or_create_atcuts an existing WAL back to the end of its last valid entry and syncs it before appending. The scan is shared withWalReader::read_entries(scan_entries).WAL-007. A checkpoint (which deletes the WAL) or a reopen gives a clean writer. Reads keep working. A rejected oversize fact (WAL-003) writes nothing and does not poison the writer.ERROR_REFERENCE.mdandMinigraf::execute).This is the WAL part of the "mark the handle failed" rule; #390 extends it to checkpoints and adds the full fault matrix.
Tests
wal.rs: torn tail cut in the checksum, header and payload; a bad-checksum entry (and everything after it) cut off; an intact WAL left byte for byte;WAL-007after a torn append (test-onlytear_next_appendhook);WAL-003does not poison.db.rs: throughMinigraf, the failed transaction is not applied,transactandcommitgiveWAL-007, andcheckpoint()makes writes work again; facts survive reopen.tests/wal_test.rs: a crashed child leaves a WAL; each torn-tail shape is appended; a second child commits and crashes; the reopen has both facts. Fails without the fix.Docs: CHANGELOG, ERROR_REFERENCE (
WAL-007), TEST_COVERAGE, test counts (1,393). Docs-site PR to follow. A v2.x backport PR tomainwill follow once this is merged.🤖 Generated with Claude Code
https://claude.ai/code/session_012wXxZguv7PgKQjMMH4yJ5h