thedotmack/claude-mem · warning
FTS5 not available — user_prompts_fts skipped (search uses C
Error message
FTS5 not available — user_prompts_fts skipped (search uses ChromaDB)
What it means
Schema migration v10 creates the `user_prompts` table plus an FTS5 virtual table (`user_prompts_fts`) and sync triggers. If the SQLite build lacks FTS5, the CREATE VIRTUAL TABLE throws; the store commits the base table anyway, records schema version 10 as applied, and warns that prompt search falls back to ChromaDB.
Source
Thrown at src/services/sqlite/SessionStore.ts:1325
VALUES('delete', old.id, old.prompt_text);
END;
CREATE TRIGGER user_prompts_au AFTER UPDATE ON user_prompts BEGIN
INSERT INTO user_prompts_fts(user_prompts_fts, rowid, prompt_text)
VALUES('delete', old.id, old.prompt_text);
INSERT INTO user_prompts_fts(rowid, prompt_text)
VALUES (new.id, new.prompt_text);
END;
`;
try {
this.db.run(ftsCreateSQL);
this.db.run(ftsTriggersSQL);
} catch (ftsError) {
if (ftsError instanceof Error) {
logger.warn('DB', 'FTS5 not available — user_prompts_fts skipped (search uses ChromaDB)', {}, ftsError);
} else {
logger.warn('DB', 'FTS5 not available — user_prompts_fts skipped (search uses ChromaDB)', {}, new Error(String(ftsError)));
}
this.db.run('COMMIT');
this.db.prepare('INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)').run(10, new Date().toISOString());
logger.debug('DB', 'Created user_prompts table (without FTS5)');
return;
}
this.db.run('COMMIT');
this.db.prepare('INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)').run(10, new Date().toISOString());
logger.debug('DB', 'Successfully created user_prompts table');
}
private ensureDiscoveryTokensColumn(): void {
const applied = this.db.prepare('SELECT version FROM schema_versions WHERE version = ?').get(11) as SchemaVersion | undefined;
if (applied) return;
View on GitHub (pinned to 8bc631a71a)
Solutions
- Accept the fallback — ChromaDB covers prompt search.
- Switch to a runtime whose SQLite has FTS5 (stock Node's node:sqlite does) and recreate the store.
- Verify capability with `SELECT * FROM pragma_compile_options() WHERE compile_options LIKE '%FTS5%'`.
Example fix
// before
// CREATE VIRTUAL TABLE ... USING fts5(...) throws on an FTS5-less SQLite
// after
const fts5 = db.prepare("SELECT 1 FROM pragma_compile_options() WHERE compile_options LIKE '%ENABLE_FTS5%'").get();
if (fts5) {
db.run(ftsCreateSQL);
db.run(ftsTriggersSQL);
} else {
// skip FTS; ChromaDB handles search
} Defensive patterns
Strategy: fallback
Validate before calling
const fts5Available = !!db.prepare("SELECT 1 FROM pragma_compile_options() WHERE compile_options LIKE '%ENABLE_FTS5%'").get(); Try / catch
try {
db.run(ftsCreateSQL);
db.run(ftsTriggersSQL);
} catch (ftsError) {
// degrade gracefully: keep the base table, rely on ChromaDB for search
logger.warn('DB', 'FTS5 not available — search falls back to ChromaDB', {}, ftsError);
} Prevention
- Use a Node/SQLite build with FTS5 enabled (stock node:sqlite includes it).
- Check pragma_compile_options once at startup and cache the capability.
When it happens
Trigger: `db.run(ftsCreateSQL)` throws because the linked SQLite was compiled without ENABLE_FTS5 (or with SQLITE_OMIT_FTS5).
Common situations: Non-standard Node builds, distro-patched SQLite without FTS5, or embedded runtimes shipping a minimal SQLite.
Related errors
- SyncApply: could not create or adopt a session for memory_se
- FTS5 table creation failed — search will use ChromaDB and LI
- FTS5 observation search failed
- FTS5 session search failed
- Failed to drop worker_pid column from pending_messages
AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20).
Data as JSON: /api/errors/2a19f244a7bd3c4e.
Report an issue: GitHub.