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

  1. Open the cursor with the index (IndexInfo) before issuing an IndexKey seek
  2. Route table cursors to integer/other seek keys instead
  3. 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

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


AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-08-20). Data as JSON: /api/errors/05c7036df7f5276d. Report an issue: GitHub.