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
- Reset the client database or clear its persisted revision so it re-bootstraps against this server.
- Keep generation-2+ clients on the endpoint that produced the rolled log.
- 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
- Reset client sync state whenever you change sync endpoints.
- Record which server (and generation) produced a persisted revision alongside the revision itself.
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
- MVCC logical pull revision is from the future: client_offset
- MVCC logical pull offset is not a transaction boundary: {off
- invalid MVCC pull revision generation: {revision}
- invalid MVCC pull revision generation: {revision}: {err}
- invalid MVCC pull revision offset: {revision}: {err}
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/ad77756caad07a04.
Report an issue: GitHub.