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

  1. Delete the segment's .idx file - it is a rebuildable cache - and let the log regenerate it from segment data
  2. If validation still fails after the rebuild, the segment data itself is damaged: quarantine/restore it
  3. 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

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


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/145fdf42463d9d7b. Report an issue: GitHub.