{"record":{"id":"05c7036df7f5276d","repo":"tursodatabase/turso","slug":"seekkey-indexkey-requires-index-cursor-type","errorCode":null,"errorMessage":"SeekKey::IndexKey requires Index cursor type","messagePattern":"SeekKey::IndexKey requires Index cursor type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/mvcc/cursor.rs","lineNumber":1669,"sourceCode":"\n                            // Set MVCC peek\n                            {\n                                self.dual_peek.mvcc_peek = match mvcc_rowid {\n                                    Some((rid, payload)) => {\n                                        self.eq_seek_row = payload;\n                                        CursorPeek::Row {\n                                            key: rid.row_id,\n                                            versions: None,\n                                        }\n                                    }\n                                    None => CursorPeek::Exhausted,\n                                };\n                            }\n                        }\n                        SeekKey::IndexKey(index_key) => {\n                            let index_info = {\n                                let MvccCursorType::Index(index_info) = &self.mv_cursor_type else {\n                                    panic!(\"SeekKey::IndexKey requires Index cursor type\");\n                                };\n                                Arc::new(IndexInfo::new_in(\n                                    index_info.key_info.iter().cloned(),\n                                    index_info.has_rowid,\n                                    index_key.column_count(),\n                                    index_info.is_unique,\n                                    self.db.allocator(),\n                                )?)\n                            };\n                            let sortable_key = SortableIndexKey::new_from_payload_in(\n                                index_key,\n                                index_info,\n                                self.db.allocator(),\n                            )?;\n\n                            // Seek in MVCC (synchronous)\n                            let mvcc_rowid = self.db.seek_index(\n                                self.table_id,","sourceCodeStart":1651,"sourceCodeEnd":1687,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/core/mvcc/cursor.rs#L1651-L1687","documentation":"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.","triggerScenarios":"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.","commonSituations":"Contributor changes to plan shapes (covering index scans, index lookups) under experimental MVCC; regressions in cursor opening order.","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"],"exampleFix":"// before\nlet result = cursor.seek(SeekKey::IndexKey(key), op)?; // table cursor -> panic\n\n// after\n// open the cursor as an index cursor before index seeks\nlet mut cursor = db.open_mvcc_index_cursor(tx_id, table_id, index_info)?;\nlet result = cursor.seek(SeekKey::IndexKey(key), op)?;","handlingStrategy":"type-guard","validationCode":"// only send index keys to index cursors\nmatch (&cursor_type, &seek_key) {\n    (MvccCursorType::Index(_), SeekKey::IndexKey(_)) => cursor.seek(seek_key, op),\n    (MvccCursorType::Table, SeekKey::IndexKey(_)) => /* reopen as index cursor first */,\n    _ => cursor.seek(seek_key, op),\n}","typeGuard":"fn accepts_index_key(t: &MvccCursorType) -> bool {\n    matches!(t, MvccCursorType::Index(_))\n}","tryCatchPattern":null,"preventionTips":["Open the cursor with the index before issuing IndexKey seeks","Diff EXPLAIN plans when changing how cursors are opened for index scans"],"tags":["mvcc","cursor","seek","index","internal","panic"],"backgroundTag":"cursor-type-mismatch","analyzedSha":"492c4a71cd7c2649e7df83da1471b74f4b1c7aa9","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}