{"record":{"id":"b281a56db827ced2","repo":"tursodatabase/turso","slug":"invalid-mvcc-pull-revision-generation-revision-b281a5","errorCode":null,"errorMessage":"invalid MVCC pull revision generation: {revision}: {err}","messagePattern":"invalid MVCC pull revision generation: (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":927,"sourceCode":"    }\n    let path = if let Some(rest) = db_path.strip_prefix(\"file:\") {\n        rest.split_once('?').map_or(rest, |(path, _)| path)\n    } else {\n        db_path\n    };\n    Ok(PathBuf::from(path))\n}\n\nfn parse_mvcc_revision_offset(revision: &str, legacy_default: u64) -> Result<u64> {\n    if revision.is_empty() {\n        return Ok(0);\n    }\n    if let Some((generation, offset)) = revision.split_once(\":o\") {\n        let generation = generation\n            .strip_prefix('g')\n            .ok_or_else(|| anyhow!(\"invalid MVCC pull revision generation: {revision}\"))?\n            .parse::<u64>()\n            .map_err(|err| anyhow!(\"invalid MVCC pull revision generation: {revision}: {err}\"))?;\n        if generation != 1 {\n            return Err(anyhow!(\n                \"sync_server supports only single-generation MVCC logical pulls: {revision}\"\n            ));\n        }\n        return offset\n            .parse::<u64>()\n            .map_err(|err| anyhow!(\"invalid MVCC pull revision offset: {revision}: {err}\"));\n    }\n    // Older page bootstrap responses from this test server used WAL frame\n    // numbers. Treat them as \"the page snapshot already includes the current\n    // logical log\" so the required follow-up logical pull becomes a no-op.\n    Ok(legacy_default)\n}\n\nfn scan_mvcc_log(log: &[u8]) -> Result<MvccLogSnapshot> {\n    if log.is_empty() {\n        return Ok(MvccLogSnapshot {","sourceCodeStart":909,"sourceCodeEnd":945,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L909-L945","documentation":"Same revision grammar as the sibling error: the generation segment starts with 'g' but the remaining digits do not parse as u64 — e.g. \"g:o9\", \"g1x:o5\", \"g-1:o3\". The underlying ParseInt error text is appended to the message so the malformed segment is identifiable.","triggerScenarios":"Hand-edited revision strings where the generation contains non-numeric characters, a sign, or is empty after the 'g'.","commonSituations":"Manual state surgery on persisted sync state; tests and scripts that template the revision string from unvalidated input.","solutions":["Validate the revision against the g<digits>:o<digits> grammar before sending.","Echo back server-provided revision strings verbatim instead of reconstructing them.","Send an empty client_revision when in doubt; the server then defines the starting offset."],"exampleFix":"// before\nreq.client_revision = \"gx1:o128\".to_string();\n\n// after\nreq.client_revision = \"g1:o128\".to_string();","handlingStrategy":"validation","validationCode":"fn is_server_revision(rev: &str) -> bool {\n    if rev.is_empty() || rev.chars().all(|c| c.is_ascii_digit()) {\n        return true;\n    }\n    matches!(\n        rev.strip_prefix('g').and_then(|r| r.split_once(\":o\")),\n        Some((g, o)) if g.parse::<u64>().is_ok() && o.parse::<u64>().is_ok()\n    )\n}","typeGuard":null,"tryCatchPattern":"On 500 'invalid MVCC pull revision generation' with a parse error, replace the malformed revision with the last server-provided one (or empty string) and retry once.","preventionTips":["Never hand-edit generation digits in persisted revisions.","Validate revisions against the grammar before sending."],"tags":["mvcc","sync","revision","protocol","validation"],"backgroundTag":"invalid-revision-format","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}