tursodatabase/turso · error
SeekKey::IndexKey requires Index cursor type
Error message
SeekKey::IndexKey requires Index cursor type
What it means
Seeking with SeekKey::IndexKey requires the cursor to have been opened as MvccCursorType::Index so key_info/has_rowid are available to rebuild the SortableIndexKey. A table cursor receiving an index seek key panics - the seek key type and the cursor type disagree.
Source
Thrown at core/mvcc/cursor.rs:1669
// Set MVCC peek
{
self.dual_peek.mvcc_peek = match mvcc_rowid {
Some((rid, payload)) => {
self.eq_seek_row = payload;
CursorPeek::Row {
key: rid.row_id,
versions: None,
}
}
None => CursorPeek::Exhausted,
};
}
}
SeekKey::IndexKey(index_key) => {
let index_info = {
let MvccCursorType::Index(index_info) = &self.mv_cursor_type else {
panic!("SeekKey::IndexKey requires Index cursor type");
};
Arc::new(IndexInfo::new_in(
index_info.key_info.iter().cloned(),
index_info.has_rowid,
index_key.column_count(),
index_info.is_unique,
self.db.allocator(),
)?)
};
let sortable_key = SortableIndexKey::new_from_payload_in(
index_key,
index_info,
self.db.allocator(),
)?;
// Seek in MVCC (synchronous)
let mvcc_rowid = self.db.seek_index(
self.table_id,View on GitHub (pinned to 492c4a71cd)
Solutions
- Open the cursor with the index (IndexInfo) before issuing an IndexKey seek
- Route table cursors to integer/other seek keys instead
- Capture the EXPLAIN output and report if reached from plain SQL
Example fix
// before let result = cursor.seek(SeekKey::IndexKey(key), op)?; // table cursor -> panic // after // open the cursor as an index cursor before index seeks let mut cursor = db.open_mvcc_index_cursor(tx_id, table_id, index_info)?; let result = cursor.seek(SeekKey::IndexKey(key), op)?;
Defensive patterns
Strategy: type-guard
Validate before calling
// only send index keys to index cursors
match (&cursor_type, &seek_key) {
(MvccCursorType::Index(_), SeekKey::IndexKey(_)) => cursor.seek(seek_key, op),
(MvccCursorType::Table, SeekKey::IndexKey(_)) => /* reopen as index cursor first */,
_ => cursor.seek(seek_key, op),
} Type guard
fn accepts_index_key(t: &MvccCursorType) -> bool {
matches!(t, MvccCursorType::Index(_))
} Prevention
- Open the cursor with the index before issuing IndexKey seeks
- Diff EXPLAIN plans when changing how cursors are opened for index scans
When it happens
Trigger: Internal: planner/translation emitting an index seek against a cursor that was opened as a table cursor under MVCC, or reusing a cursor for both key kinds without reopening.
Common situations: Contributor changes to plan shapes (covering index scans, index lookups) under experimental MVCC; regressions in cursor opening order.
Related errors
- Invalid btree seek state in seek_btree_and_set_peek: {:?}
- RowKey::Record requires Index cursor type
- invalid position to read current mvcc row
- Cursor not found: {key:?}
- Cursor not found: {cursor_id}
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-08-20).
Data as JSON: /api/errors/05c7036df7f5276d.
Report an issue: GitHub.