clockworklabs/SpacetimeDB · error · io::Error
No valid commit found in index up to key: {candidate_last_ke
Error message
No valid commit found in index up to key: {candidate_last_key} What it means
While validating/rebuilding an offset index, the code walked candidate keys downward (decrementing on every entry that failed validation) and reached 0 without finding a single valid commit (InvalidData). The index contains no entry consistent with the segment data - typically an empty-but-present index, or one that belongs to different segment contents.
Source
Thrown at crates/commitlog/src/segment.rs:745
},
size_in_bytes: byte_offset + commit.size_in_bytes,
max_epoch: commit.epoch,
max_commit_offset: commit.tx_range.start,
max_commit: Some(commit),
});
}
// `TxOffset` at `byte_offset` is not valid, so try with previous entry
Err(_) => {
candidate_last_key = key.saturating_sub(1);
if candidate_last_key == 0 {
break;
}
}
}
}
Err(io::Error::new(
ErrorKind::InvalidData,
format!("No valid commit found in index up to key: {candidate_last_key}"),
))
}
/// Validates and decodes a commit at `byte_offset` in the segment.
///
/// # Returns
/// * `Ok(commit::Metadata)` - If a valid commit is found with matching transaction offset
/// * `Err` - If commit can't be decoded or has mismatched transaction offset
fn validate_commit_at_offset<R: io::Read + io::Seek>(
reader: &mut R,
tx_offset: TxOffset,
byte_offset: u64,
) -> io::Result<commit::Metadata> {
reader.seek(SeekFrom::Start(byte_offset))?;
let commit = commit::Metadata::extract(reader)?
.ok_or_else(|| io::Error::new(ErrorKind::InvalidData, "failed to decode commit"))?;View on GitHub (pinned to 524b4487d9)
Solutions
- Delete the segment's .idx file - it is a rebuildable cache - and let the log regenerate it from segment data
- If validation still fails after the rebuild, the segment data itself is damaged: quarantine/restore it
- Prevent external modification of the directory while the log is open
Defensive patterns
Strategy: fallback
Type guard
fn is_index_unusable(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::InvalidData
&& e.to_string().contains("No valid commit found in index")
} Try / catch
match rebuild_index_for(&segment) {
Ok(idx) => idx,
Err(e) if is_index_unusable(&e) => {
// no index entry matches the data: delete .idx and rebuild from the segment itself
std::fs::remove_file(index_path_for(&segment))?;
rebuild_index_for(&segment)?
}
Err(e) => return Err(e),
} Prevention
- Remember .idx files are rebuildable caches: deleting them (log closed) is always safe
- Keep backup/restore procedures from mixing .idx files of one segment with another
- Forbid external tools from rewriting segment files in the log directory
When it happens
Trigger: The segment was rewritten or truncated while its old .idx file was kept; an .idx from a different segment was copied in; wholesale index corruption so every candidate entry fails validation.
Common situations: Manual file surgery on the data directory; backup/restore procedures that mix index files and segments; crashes during initial index creation.
Related errors
- mismatched key in offset index file
- InvalidData
- segment header does not start with magic: expected {:02x?},
- unexpected EOF while validating commit at byte offset {byte_
- out-of-order offset: expected={} actual={}
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/145fdf42463d9d7b.
Report an issue: GitHub.