SQLite has a rare data race between a checkpoint and a concurrent write transaction, known as the "WAL-Reset bug". If a write lands at just the wrong moment during a checkpoint, the checkpointing code wrongly concludes that some pages have already been copied from the write-ahead log into the main database file. Those pages are never written, so the committed data is permanently lost.
The database is left corrupt rather than merely incomplete: other pages that reference the lost ones (indexes, for instance) do get written, so integrity checks later report referential-integrity violations. The bug has been present since SQLite 3.7.0 (July 2010), when WAL mode was introduced, and went unnoticed for about 16 years because it needs extremely tight timing and WAL mode with concurrent connections. Tailscale hit it in production, seeing 19 separate database corruption incidents across shards over roughly six months starting in August 2025, and only traced it to SQLite in February 2026 after building custom VFS-level logging tools. Tailscale was unusually exposed because it drives checkpointing manually and aggressively rather than letting SQLite handle it.
Steps to reproduce:
- Open an SQLite database in WAL mode with multiple concurrent connections.
- Run a sustained write workload (repeated insert transactions) on one connection.
- Concurrently and repeatedly invoke checkpoints from another connection.
- Let the workload run until the race is hit (Antithesis reported reproducing it in about 15 minutes using deterministic fault-injection testing; hitting it on ordinary hardware is far less likely).
- Run
PRAGMA integrity_checkand look for missing pages / referential-integrity violations.
Workaround: No real user-facing workaround short of upgrading. Exposure can be reduced by not taking manual control of checkpointing (letting SQLite do automatic checkpoints) and avoiding aggressive checkpointing under concurrent writes, since that pattern makes the race far more likely. Corrupted databases must be restored from backup.
Severity: Critical (silent, permanent data loss and database corruption in the default durability path, with no workaround other than upgrading; mitigated only by how rarely the timing window is hit in typical usage)
First seen: August 2025 (first Tailscale corruption incident); root cause identified February 2026
Affected product: SQLite
Affected platforms: All platforms
Affected versions: 3.7.0 (July 2010) through 3.51.2, when WAL mode is used
Fixed versions: 3.51.3 (3.52.0 was withdrawn)
Links:
- https://tailscale.com/blog/sqlite-wal-reset-bug (August 2026)
- https://antithesis.com/blog/2026/wal-reset-bug/ (2026)
- https://www.theregister.com/databases/2026/08/12/tailscale-says-deeply-buried-16-year-old-sqlite-bug-caused-last-years-outages/5287004 (12 August 2026)
- https://www.techzine.eu/news/infrastructure/143585/old-sqlite-bug-caused-months-of-outages-at-tailscale/ (August 2026)
- https://ubuntu.com/blog/hunting-a-16-year-old-sqlite-bug-with-tla-is-dqlite-affected (2026)