Skip to content

Commit fe5b736

Browse files
committed
fix: gracefully handle missing SQLite FTS5 on Windows
Probes FTS5 availability with an in-memory test table before attempting index operations. When FTS5 is missing (common on Windows Node.js binaries), throws SearchDepsUnavailableError so existing handlers skip indexing gracefully instead of crashing. Closes #64
1 parent 515f7b7 commit fe5b736

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

src/retriv/index.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,47 @@ export type { ChunkEntity, Document, IndexConfig, IndexPhase, IndexProgress, Sea
66
type RetrivInstance = Awaited<ReturnType<typeof getDb>>
77

88
export class SearchDepsUnavailableError extends Error {
9-
constructor(cause: unknown) {
10-
super('Search dependencies unavailable (sqlite-vec or retriv not installed). Search indexing skipped.')
9+
constructor(cause: unknown, message?: string) {
10+
super(message ?? 'Search dependencies unavailable (sqlite-vec or retriv not installed). Search indexing skipped.')
1111
this.name = 'SearchDepsUnavailableError'
1212
this.cause = cause
1313
}
1414
}
1515

16+
let _fts5Available: boolean | null = null
17+
18+
/**
19+
* Probe whether SQLite FTS5 module is available.
20+
* Windows Node.js binaries often ship without FTS5 compiled in.
21+
*/
22+
function checkFts5(): boolean {
23+
if (_fts5Available !== null)
24+
return _fts5Available
25+
const nodeSqlite = globalThis.process?.getBuiltinModule?.('node:sqlite') as typeof import('node:sqlite') | undefined
26+
if (!nodeSqlite) {
27+
_fts5Available = false
28+
return false
29+
}
30+
const db = new nodeSqlite.DatabaseSync(':memory:')
31+
try {
32+
db.exec('CREATE VIRTUAL TABLE _fts5_probe USING fts5(content)')
33+
db.exec('DROP TABLE _fts5_probe')
34+
_fts5Available = true
35+
}
36+
catch {
37+
_fts5Available = false
38+
}
39+
finally {
40+
db.close()
41+
}
42+
return _fts5Available
43+
}
44+
1645
// Dynamic imports: retriv/chunkers/auto eagerly loads typescript which may not be installed (e.g. npx)
1746
export async function getDb(config: Pick<IndexConfig, 'dbPath'>) {
47+
if (!checkFts5())
48+
throw new SearchDepsUnavailableError(new Error('FTS5 module not available'), 'SQLite FTS5 module not available. Search indexing skipped. On Windows, run from WSL where FTS5 is included.')
49+
1850
let createRetriv, autoChunker, sqliteMod, sqliteVec, transformersJs, cachedEmbeddings
1951
try {
2052
;([

0 commit comments

Comments
 (0)