{"record":{"id":"31f90cfa7ca56f54","repo":"neondatabase/neon","slug":"invalid-record-block-len","errorCode":null,"errorMessage":"invalid {:?} record: block.len()={}","messagePattern":"invalid (.+?) record: block\\.len\\(\\)=(.+?)","errorType":"exception","errorClass":"BasebackupError","httpStatus":null,"severity":"error","filePath":"pageserver/src/basebackup.rs","lineNumber":268,"sourceCode":"            total_blocks: 0,\n        }\n    }\n\n    async fn add_block(&mut self, key: &Key, block: Bytes) -> Result<(), BasebackupError> {\n        let (kind, segno, _) = key.to_slru_block()?;\n\n        match kind {\n            SlruKind::Clog => {\n                if !(block.len() == BLCKSZ as usize || block.len() == BLCKSZ as usize + 8) {\n                    return Err(BasebackupError::Server(anyhow!(\n                        \"invalid SlruKind::Clog record: block.len()={}\",\n                        block.len()\n                    )));\n                }\n            }\n            SlruKind::MultiXactMembers | SlruKind::MultiXactOffsets => {\n                if block.len() != BLCKSZ as usize {\n                    return Err(BasebackupError::Server(anyhow!(\n                        \"invalid {:?} record: block.len()={}\",\n                        kind,\n                        block.len()\n                    )));\n                }\n            }\n        }\n\n        let segment = (kind, segno);\n        match self.current_segment {\n            None => {\n                self.current_segment = Some(segment);\n                self.buf\n                    .extend_from_slice(block.slice(..BLCKSZ as usize).as_ref());\n            }\n            Some(current_seg) if current_seg == segment => {\n                self.buf\n                    .extend_from_slice(block.slice(..BLCKSZ as usize).as_ref());","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/src/basebackup.rs#L250-L286","documentation":"The same SLRU segment builder validates pg_multixact_offsets and pg_multixact_members page images: they must be exactly BLCKSZ. Any other length means the multixact SLRU page reconstructed from layers is malformed, and the basebackup aborts with the SLRU kind and offending length in the message.","triggerScenarios":"A MultiXactMembers or MultiXactOffsets block image with size != 8192 served during basebackup: layer corruption, a reconstruction bug for multixact keys, or page-layout skew from version changes.","commonSituations":"Workloads with heavy shared-row locking (multixacts) hitting a damaged layer; branches spanning neon versions with multixact format changes.","solutions":["Check pageserver logs for the failing key and layer","Retry the basebackup at a different LSN to see whether the damage is LSN-bounded","Validate or re-download the implicated layers from remote storage","If corruption is confirmed, recover from a healthy branch or backup"],"exampleFix":"// before: size checked only inside the builder during basebackup\n// after: validate on read so callers learn the key, not just the length\nlet (kind, segno, blk) = key.to_slru_block()?;\nif kind.is_multixact() && img.len() != 8192 {\n    anyhow::bail!(\"corrupt {kind:?} page seg {segno} blk {blk}: len {}\", img.len());\n}","handlingStrategy":"validation","validationCode":"// scrub multixact SLRU blocks ahead of a backup window\nfor kind in [SlruKind::MultiXactOffsets, SlruKind::MultiXactMembers] {\n    for key in scan_slru_keys(kind).await? {\n        let img = timeline.get(key, lsn, ctx).await?;\n        if img.len() != 8192 {\n            alert_corruption(ttid, key, img.len());\n        }\n    }\n}","typeGuard":"fn is_valid_slru_page(kind: SlruKind, img: &bytes::Bytes) -> bool {\n    match kind {\n        SlruKind::Clog => matches!(img.len(), 8192 | 8200),\n        _ => img.len() == 8192,\n    }\n}","tryCatchPattern":"Err(e) if e.to_string().contains(\"record: block.len()\") => {\n    // parse the kind and length from the message; open a corruption investigation\n}","preventionTips":["Schedule layer validation between backup windows","Alert on any basebackup abort mentioning block.len()","Keep multixact-heavy workloads on monitored tenants","Cross-check remote object checksums after uploads"],"tags":["pageserver","basebackup","slru","multixact","data-integrity","page-validation"],"backgroundTag":"corrupt-page-image","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}