fix: Gracefully handle FTS5 unavailability in sql.js fallback (#398)

Fixed critical startup crash when server falls back to sql.js adapter
due to Node.js version mismatches.

Problem:
- better-sqlite3 fails to load when Node runtime version differs from build version
- Server falls back to sql.js (pure JS, no native dependencies)
- Database health check crashed with "no such module: fts5"
- Server exits immediately, preventing Claude Desktop connection

Solution:
- Wrapped FTS5 health check in try-catch block
- Logs warning when FTS5 not available
- Server continues with fallback search (LIKE queries)
- Graceful degradation: works with any Node.js version

Impact:
- Server now starts successfully with sql.js fallback
- Works with Node v20 (Claude Desktop) even when built with Node v22
- Clear warnings about FTS5 unavailability
- Users can choose: sql.js (slower, works everywhere) or rebuild better-sqlite3 (faster)

Files Changed:
- src/mcp/server.ts: Added try-catch around FTS5 health check (lines 299-317)

Testing:
-  Tested with Node v20.17.0 (Claude Desktop)
-  Tested with Node v22.17.0 (build version)
-  All 6 startup checkpoints pass
-  Database health check passes with warning

Fixes: Claude Desktop connection failures with Node.js version mismatches

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en
This commit is contained in:
Romuald Członkowski
2025-11-04 16:14:16 +01:00
committed by GitHub
parent 65f51ad8b5
commit a4ef1efaf8
4 changed files with 114 additions and 13 deletions

View File

@@ -296,19 +296,24 @@ export class N8NDocumentationMCPServer {
throw new Error('Database is empty. Run "npm run rebuild" to populate node data.');
}
// Check if FTS5 table exists
const ftsExists = this.db.prepare(`
SELECT name FROM sqlite_master
WHERE type='table' AND name='nodes_fts'
`).get();
// Check if FTS5 table exists (wrap in try-catch for sql.js compatibility)
try {
const ftsExists = this.db.prepare(`
SELECT name FROM sqlite_master
WHERE type='table' AND name='nodes_fts'
`).get();
if (!ftsExists) {
logger.warn('FTS5 table missing - search performance will be degraded. Please run: npm run rebuild');
} else {
const ftsCount = this.db.prepare('SELECT COUNT(*) as count FROM nodes_fts').get() as { count: number };
if (ftsCount.count === 0) {
logger.warn('FTS5 index is empty - search will not work properly. Please run: npm run rebuild');
if (!ftsExists) {
logger.warn('FTS5 table missing - search performance will be degraded. Please run: npm run rebuild');
} else {
const ftsCount = this.db.prepare('SELECT COUNT(*) as count FROM nodes_fts').get() as { count: number };
if (ftsCount.count === 0) {
logger.warn('FTS5 index is empty - search will not work properly. Please run: npm run rebuild');
}
}
} catch (ftsError) {
// FTS5 not supported (e.g., sql.js fallback) - this is OK, just warn
logger.warn('FTS5 not available - using fallback search. For better performance, ensure better-sqlite3 is properly installed.');
}
logger.info(`Database health check passed: ${nodeCount.count} nodes loaded`);