tursodatabase/turso · critical
database page {} is missing from replace-base snapshot
Error message
database page {} is missing from replace-base snapshot What it means
When serving a replace-base (full snapshot) response, the server walks pages 1..=db_size reading each through the WAL at the max_frame watermark. try_wal_watermark_read_page returning false means a page the header says exists is invisible at that watermark, i.e. the WAL view is inconsistent. The constructor calls wal_auto_actions_disable() precisely to keep this watermark stable, so hitting the error means something checkpointed, reset, or truncated the WAL concurrently, the WAL is damaged, or the watermark read has a bug; the server refuses rather than emit a silently corrupt snapshot.
Source
Thrown at cli/sync_server.rs:862
#[allow(clippy::type_complexity)]
fn read_replace_base_pages(&self) -> Result<(u64, Vec<(u64, Vec<u8>)>)> {
let conn = self.conn.lock().unwrap();
let wal_state = conn.wal_state()?;
let frame_watermark = Some(wal_state.max_frame);
let db_size = current_snapshot_db_size_pages(&conn, wal_state.max_frame)?;
let pages_capacity = usize::try_from(db_size)
.map_err(|_| anyhow!("database page count does not fit usize: {db_size}"))?;
let mut pages = Vec::with_capacity(pages_capacity);
for page_no in 1..=db_size {
let page_no_u32 = u32::try_from(page_no)
.map_err(|_| anyhow!("database page number does not fit u32: {page_no}"))?;
let mut page = vec![0; PAGE_SIZE];
let found =
conn.try_wal_watermark_read_page(page_no_u32, &mut page, frame_watermark)?;
if !found {
return Err(anyhow!(
"database page {} is missing from replace-base snapshot",
page_no
));
}
pages.push((page_no - 1, page));
}
Ok((db_size, pages))
}
}
struct HttpResponse {
status: u16,
content_type: String,
body: Vec<u8>,
}
struct MvccLogSnapshot {View on GitHub (pinned to bad083fafb)
Solutions
- Stop every other writer/checkpointer on the .db/.wal files while the sync server is running.
- Restart the sync server so it re-establishes a stable WAL watermark, then retry the pull.
- Run integrity checks on the database and WAL; if files are damaged, rebuild the server db and re-bootstrap clients.
- If it reproduces with a single isolated server, file a tursodb bug attaching the .db, -wal, and .db-log files.
Defensive patterns
Strategy: retry
Try / catch
On 500 'database page N is missing from replace-base snapshot': stop all other processes touching the .db/.wal, restart the sync server to re-establish a stable WAL watermark, then retry the pull. If it recurs on an isolated server, treat the files as damaged, rebuild, and re-bootstrap clients.
Prevention
- Give the sync server exclusive access: never run sqlite3 CLI checkpoints or other writers against its database.
- Run at most one sync server per database file.
- Do not re-enable WAL auto actions on the server connection: wal_auto_actions_disable() is what keeps the watermark read consistent.
When it happens
Trigger: An external process (sqlite3 CLI checkpoint, another tursodb connection, a second sync server) checkpointing or resetting the WAL mid-pull; deleting or truncating the -wal file while the server runs; WAL corruption after a crash; an engine bug in try_wal_watermark_read_page.
Common situations: Mixing CLI tools and the sync server on one database file; running two experiments against the same db; crash-damaged WAL files.
Related errors
- database page number does not fit u32: {page_no}
- checkpoint() is only available for sync databases
- Failed to parse server_pages_selector: {}
- MVCC logical log header checksum mismatch
- No active remote transaction
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/189011ba319631c9.
Report an issue: GitHub.