tursodatabase/turso · critical
No WAL to checkpoint
Error message
No WAL to checkpoint
What it means
checkpoint_wal in the MVCC checkpoint state machine performs a TRUNCATE checkpoint but panics if self.pager.wal is None, i.e. the pager was opened without a WAL. The state machine should only run when a WAL exists, so hitting this panic means the checkpoint driver was started on a non-WAL (or already torn down) pager.
Source
Thrown at core/mvcc/database/checkpoint_state_machine.rs:1485
let boundary = if self.mode.should_restart_log() {
u64::MAX
} else {
self.durable_txid_max_new
};
let (c, outcome) = self.mvstore.storage.truncate(boundary)?;
if self.mode.should_restart_log() {
turso_assert!(
matches!(outcome, LogicalLogTruncateOutcome::Truncated),
"TRUNCATE checkpoint must clear the logical log"
);
}
Ok(c)
}
/// Perform a TRUNCATE checkpoint on the WAL
fn checkpoint_wal(&self) -> IOResultOr<CheckpointResult> {
let Some(wal) = &self.pager.wal else {
panic!("No WAL to checkpoint");
};
match wal.checkpoint(&self.pager, self.mode, self.sync_mode)? {
IOResult::Done(result) => Ok(IOResult::Done(result)),
IOResult::IO(io) => Ok(IOResult::IO(io)),
}
}
/// Publish `nbackfills` after Passive backfill + DB sync. Skip Truncate/Restart.
/// Leaves the checkpoint guard held until Finalize (same as the pager).
fn publish_wal_backfill_if_needed(&mut self) {
if self.mode.should_restart_log() {
return;
}
let Some(result) = self.checkpoint_result.as_ref() else {
return;
};
if result.wal_checkpoint_backfilled == 0 {
return;View on GitHub (pinned to 492c4a71cd)
Solutions
- Ensure the database is opened in WAL journal mode before triggering MVCC checkpointing.
- Avoid closing/destroying the database while a checkpoint is still pending; complete or cancel checkpointing first.
- File a bug with reproduction steps if this occurs in normal WAL-mode operation.
- If developing the engine, add a guard so the checkpoint state machine is never entered without a WAL.
Defensive patterns
Strategy: validation
Validate before calling
// Only schedule MVCC checkpointing when the pager actually has a WAL
if (db.pager.wal.is_some()) {
checkpoint_driver.start();
} Try / catch
// Rust panic: prevent entry into the state machine rather than catching it assert!(pager.wal.is_some(), "checkpoint requires WAL mode");
Prevention
- Open MVCC databases in WAL journal mode.
- Complete or cancel pending checkpoints before closing the database.
- Don't detach/close the WAL while background checkpoint tasks are scheduled.
When it happens
Trigger: Driving the MVCC checkpoint state machine on a pager opened without WAL support, or after the WAL has been detached/closed while checkpointing is still in progress.
Common situations: Running MVCC-mode experiments with a journal mode that isn't WAL; shutting down a database while a background checkpoint is scheduled; engine development/fuzzing of the checkpoint path.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- result should be set
- checkpoint() is only available for sync databases
- Cannot eval AggregateOperator with Uninitialized state
- InvalidData
- UnexpectedEof
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-09-06).
Data as JSON: /api/errors/51fc8558a66efa3c.
Report an issue: GitHub.