{"record":{"id":"3782b4997469e342","repo":"clockworklabs/SpacetimeDB","slug":"failed-to-truncate-offset-index-e","errorCode":null,"errorMessage":"Failed to truncate offset index: {e}","messagePattern":"Failed to truncate offset index: (.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/commitlog/src/commitlog.rs","lineNumber":742,"sourceCode":"                    break;\n                }\n                byte_offset += Commit::from(commit).encoded_len() as u64;\n            }\n\n            if byte_offset == segment::Header::LEN as u64 {\n                // Segment is empty, just remove it.\n                repo.remove_segment(segment)?;\n            } else {\n                debug!(\"truncating segment {segment} to {offset} at {byte_offset}\");\n                let mut file = repo.open_segment_writer(segment)?;\n\n                if let Some(mut index_file) = index_file {\n                    let index_file = index_file.as_mut();\n                    // Note: The offset index truncates equal or greater,\n                    // inclusive. We'd like to retain `offset` in the index, as\n                    // the commit is also retained in the log.\n                    index_file.ftruncate(offset + 1, byte_offset).map_err(|e| {\n                        io::Error::new(\n                            io::ErrorKind::InvalidData,\n                            format!(\"Failed to truncate offset index: {e}\"),\n                        )\n                    })?;\n                    index_file.async_flush()?;\n                }\n\n                file.ftruncate(offset, byte_offset)?;\n                // We should be reopening the log anyway, but just in case.\n                file.seek(io::SeekFrom::End(0))?;\n                // Some filesystems require fsync after ftruncate.\n                file.fsync()?;\n                break;\n            }\n        }\n    }\n\n    Ok(())","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/9e0d92412ff2248f401a8ad12d535f2b5ac30912/crates/commitlog/src/commitlog.rs#L724-L760","documentation":"Raised during Commitlog::truncate: after a segment file is cut back to a given commit offset, the matching offset-index file must also be truncated (to offset + 1, since the retained commit stays indexed). If index_file.ftruncate fails, the error is wrapped as InvalidData with this message, leaving the index and segment potentially out of sync until truncation is retried.","triggerScenarios":"Truncating a commitlog when the offset-index truncate fails: permissions changed on the index file, the file was deleted by another process, the volume went read-only or full, or an IO error occurred during ftruncate.","commonSituations":"Recovery after a crash while something else (backup job, antivirus, ops script) touches the data directory; full or read-only disks during recovery.","solutions":["Fix the filesystem condition: free space, remount read-write, restore ownership/permissions on the index files.","Retry the truncation/recovery once the data directory is healthy.","Ensure nothing else modifies or removes index files while the node runs."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = commitlog.truncate(offset, byte_offset) {\n    if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains(\"offset index\") {\n        // repair filesystem (space/permissions) then retry the truncation once\n    } else {\n        return Err(e.into());\n    }\n}","preventionTips":["Keep the data directory on healthy, writable local storage with free space headroom.","Do not run backup/cleanup jobs that delete or lock index files under a live node.","After any manual segment surgery, verify segment and index sizes agree before restarting the node."],"tags":["rust","commitlog","truncation","offset-index","io"],"backgroundTag":"index-truncation-failed","analyzedSha":"9e0d92412ff2248f401a8ad12d535f2b5ac30912","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}