{"record":{"id":"7d9e8dc44a12c8c9","repo":"clockworklabs/SpacetimeDB","slug":"invaliddata-7d9e8d","errorCode":"InvalidData","errorMessage":"repo {}: too many empty segments: {}","messagePattern":"repo (.+?): too many empty segments: (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/commitlog/src/commitlog.rs","lineNumber":476,"sourceCode":"            mut segment_reader,\n        }) = open_newest_non_empty_segment(&repo)?\n        else {\n            return Ok(None);\n        };\n        let offset_index = repo.get_offset_index(segment_offset).ok();\n        match segment::Metadata::extract(segment_offset, &mut segment_reader, offset_index.as_ref()) {\n            // Segment is intact.\n            Ok(metadata) if empty_segments <= 1 => {\n                assert!(\n                    !metadata.tx_range.is_empty(),\n                    \"segment was promised to be non-empty but contains zero transactions\"\n                );\n                Ok(Some(CommittedMeta::Complete { metadata }))\n            }\n            // Segment is good, but there are too many empty segments.\n            Ok(metadata) => Ok(Some(CommittedMeta::Prefix {\n                metadata,\n                error: io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    format!(\"repo {}: too many empty segments: {}\", repo, empty_segments),\n                ),\n            })),\n            // Segment is non-empty, but first commit is corrupt.\n            Err(error::SegmentMetadata::InvalidCommit { sofar, source }) if sofar.tx_range.is_empty() => {\n                Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    format!(\n                        \"repo {}: first commit in the most recent segment is corrupt: {}\",\n                        repo, source\n                    ),\n                ))\n            }\n            // Some prefix of the segment is good.\n            Err(error::SegmentMetadata::InvalidCommit { sofar, source }) => Ok(Some(CommittedMeta::Prefix {\n                metadata: sofar,\n                error: source,","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/commitlog/src/commitlog.rs#L458-L494","documentation":"On repository open, the commitlog scans the newest segments and tolerates at most one empty (zero-transaction) segment, which a single crash can leave behind. More than one consecutive empty segment yields `CommittedMeta::Prefix` whose error is InvalidData 'repo {name}: too many empty segments: {n}' — the log still opens, but only up to the recovered prefix. Repeated crash-loops that never commit are the typical producer.","triggerScenarios":"Opening a repository whose newest consecutive segments contain zero transactions, with count greater than 1 — several crash-restart cycles each creating a segment with no commit.","commonSituations":"Host crash-looping (OOM killer, startup panic, container restart storm) — every restart that opens a new segment without committing adds one empty segment.","solutions":["Fix the crash loop first (OOM, startup panic) — each failed restart adds another empty segment","Move aside or delete the trailing empty segment files, keeping at most one","Reopen the repository; it recovers to the prefix and new commits re-extend the log"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match open_repository(cfg) {\n    Ok((log, CommittedMeta::Prefix { error, .. })) => {\n        // opened at a prefix: \"too many empty segments\" is a crash-loop signature;\n        // investigate before more empty segments accumulate\n        tracing::warn!(\"commitlog opened at prefix: {error}\");\n    }\n    Ok((_log, CommittedMeta::Complete { .. })) => { /* normal recovery */ }\n    Err(e) => return Err(e),\n}","preventionTips":["Alert on repeated host restarts with no commits — each adds an empty segment","Fix startup crash loops (OOM, panics) before reopening the database","When pruning manually, keep at most one trailing empty segment"],"tags":["rust","commitlog","recovery","empty-segments"],"backgroundTag":"log-recovery-anomaly","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}