{"record":{"id":"caa6eaf22a9280bf","repo":"tursodatabase/turso","slug":"invalid-mvcc-pull-revision-offset-revision-er","errorCode":null,"errorMessage":"invalid MVCC pull revision offset: {revision}: {err}","messagePattern":"invalid MVCC pull revision offset: (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":935,"sourceCode":"\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 {\n            end_offset: 0,\n            crc_by_offset: vec![(0, 0)],\n        });\n    }\n    if log.len() < MVCC_LOG_HEADER_SIZE {\n        return Err(anyhow!(\n            \"truncated MVCC logical log header: len={} header_size={}\",\n            log.len(),","sourceCodeStart":917,"sourceCodeEnd":953,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L917-L953","documentation":"The offset segment after \":o\" in the client revision fails u64 parsing — e.g. \"g1:olast\", \"g1:o-5\", or a missing value like \"g1:o\". The generation parsed fine, so the message pinpoints only the offset part, with the ParseInt error appended.","triggerScenarios":"Hand-crafted or template-substituted revision strings whose offset is non-numeric, signed, or empty.","commonSituations":"Tests substituting symbolic names into the revision format; persisted state corrupted or truncated at the offset field.","solutions":["Validate the revision against the g<digits>:o<digits> grammar before sending.","Use server-provided revision strings verbatim; never template them.","Send an empty client_revision when the correct offset is unknown."],"exampleFix":"// before\nreq.client_revision = \"g1:oend\".to_string();\n\n// after\nreq.client_revision = \"g1:o128\".to_string();","handlingStrategy":"validation","validationCode":"fn valid_offset(rev: &str) -> bool {\n    rev.strip_prefix(\"g1:o\").map(|o| !o.is_empty() && o.chars().all(|c| c.is_ascii_digit())).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"On 500 'invalid MVCC pull revision offset', substitute the last server-provided revision (or empty string for offset 0) and retry once.","preventionTips":["Never template the offset from unvalidated input.","Echo server-provided revisions verbatim."],"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"}