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

  1. Stop every other writer/checkpointer on the .db/.wal files while the sync server is running.
  2. Restart the sync server so it re-establishes a stable WAL watermark, then retry the pull.
  3. Run integrity checks on the database and WAL; if files are damaged, rebuild the server db and re-bootstrap clients.
  4. 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

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


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/189011ba319631c9. Report an issue: GitHub.