tursodatabase/turso · error

database page number does not fit u32: {page_no}

Error message

database page number does not fit u32: {page_no}

What it means

When serving replace-base pages, each page number in 1..=db_size is converted to u32 before calling try_wal_watermark_read_page. db_size greater than u32::MAX fails the conversion. SQLite-family databases store the page count in a 32-bit header field, so a value this large indicates corrupt snapshot metadata rather than a real database.

Source

Thrown at cli/sync_server.rs:857

            status: 200,
            content_type: "application/protobuf".to_string(),
            body: response_body,
        })
    }

    #[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,

View on GitHub (pinned to bad083fafb)

Solutions

  1. Treat db_size > u32::MAX as corruption: verify the database header and WAL snapshot.
  2. Rebuild the server database and re-bootstrap clients if metadata is damaged.
  3. No real database reaches this size; do not attempt to serve it.
Defensive patterns

Strategy: validation

Validate before calling

if reported_page_count > u32::MAX as u64 {
    return Err("page count beyond u32 cannot be a real SQLite-family db; treat as corruption".into());
}

Prevention

When it happens

Trigger: A corrupt or fabricated db_size above u32::MAX reaching the replace-base page loop on any platform.

Common situations: Damaged WAL snapshot metadata after a crash; tests that inject arbitrary db_size values.

Related errors


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