tursodatabase/turso · error

sync_server supports only single-generation MVCC logical pul

Error message

sync_server supports only single-generation MVCC logical pulls: {revision}

What it means

The generation number parses but is not 1 — e.g. "g2:o100". Multi-generation logical logs exist after a production server checkpoints and rolls its log; this local server scans only single-generation 'lml3' logs (generation 1), so it refuses to serve offsets from later generations with HTTP 500.

Source

Thrown at cli/sync_server.rs:929

        rest.split_once('?').map_or(rest, |(path, _)| path)
    } else {
        db_path
    };
    Ok(PathBuf::from(path))
}

fn parse_mvcc_revision_offset(revision: &str, legacy_default: u64) -> Result<u64> {
    if revision.is_empty() {
        return Ok(0);
    }
    if let Some((generation, offset)) = revision.split_once(":o") {
        let generation = generation
            .strip_prefix('g')
            .ok_or_else(|| anyhow!("invalid MVCC pull revision generation: {revision}"))?
            .parse::<u64>()
            .map_err(|err| anyhow!("invalid MVCC pull revision generation: {revision}: {err}"))?;
        if generation != 1 {
            return Err(anyhow!(
                "sync_server supports only single-generation MVCC logical pulls: {revision}"
            ));
        }
        return offset
            .parse::<u64>()
            .map_err(|err| anyhow!("invalid MVCC pull revision offset: {revision}: {err}"));
    }
    // Older page bootstrap responses from this test server used WAL frame
    // numbers. Treat them as "the page snapshot already includes the current
    // logical log" so the required follow-up logical pull becomes a no-op.
    Ok(legacy_default)
}

fn scan_mvcc_log(log: &[u8]) -> Result<MvccLogSnapshot> {
    if log.is_empty() {
        return Ok(MvccLogSnapshot {
            end_offset: 0,
            crc_by_offset: vec![(0, 0)],

View on GitHub (pinned to bad083fafb)

Solutions

  1. Reset the client database or clear its persisted revision so it re-bootstraps against this server.
  2. Keep generation-2+ clients on the endpoint that produced the rolled log.
  3. If this must work locally, recreate the local .db/.db-log pair so the server serves generation 1 from the start.

Example fix

// before
req.client_revision = "g2:o100".to_string();

// after: re-bootstrap, then adopt the returned revision
req.client_revision = String::new(); // response gives "g1:o<end>" to persist
Defensive patterns

Strategy: fallback

Try / catch

On 500 'sync_server supports only single-generation MVCC logical pulls', clear the client revision (or reset the client db), re-bootstrap against this server, and persist the returned g1:o<end> revision; retrying a g2+ revision against this server can never succeed.

Prevention

When it happens

Trigger: A client that previously synced against a production Turso endpoint (generation >= 2) is repointed at this local single-generation sync server without resetting its persisted state.

Common situations: Promoting a client from production to a local test server (or vice versa); long-lived test fixtures whose revisions outlive server log roll-overs.

Related errors


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