Problem
context-mode crashes intermittently with SIGSEGV (Signal 11) when running on Node.js v22/v24 on Linux due to a V8 runtime bug that corrupts better-sqlite3's native addon .got.plt section.
Root cause
V8's garbage collector calls madvise(MADV_DONTNEED) on memory ranges that can overlap better_sqlite3.node's writable ELF segments (.got.plt). This discards resolved symbol addresses on Copy-on-Write pages, restoring unrelocated on-disk offsets — causing function calls to jump to near-null addresses.
Upstream issue: nodejs/node#62515 — "Sporadic SIGSEGV: native addon .got.plt reset to unrelocated file offsets"
Why context-mode is especially affected
- Runs as an MCP server over stdio pipes (the documented trigger condition)
- Makes frequent
better-sqlite3 calls for FTS5 indexing and search
- High call frequency under sustained I/O maximizes exposure to the race condition
Crash frequency
| Node Version |
Crash Frequency |
Tested On |
| v24.14.x |
~4 crashes/hour |
Ubuntu 24.04, Linux 6.19.10, AMD x86-64 |
| v22.22.x |
~1 crash/2 hours |
Same environment |
All coredumps show the same pattern: frame #0 at near-null address (0x12xxx range), consistent with .got.plt corruption.
What doesn't help
| Attempted Fix |
Result |
| Downgrade Node v24 → v22 |
Reduced frequency ~10x, did not eliminate |
| Upgrade better-sqlite3 to v12.8.0 (V8 HolderV2 fix) |
No effect — crash persists |
LD_BIND_NOW=1 (eager symbol resolution) |
Partial — changes memory layout only |
LD_PRELOAD madvise guard (intercept+block on .node segments) |
Effective but fragile — requires compiled C library, supervisor wrapper, auto-heal hook |
The only reliable fix is eliminating the separate .node binary that gets dlopen()'d as a standalone ELF file.
Proposal: Support pluggable SQLite backends
The codebase already has the right abstraction for this:
BunSQLiteAdapter (db-base.ts:40-104) already bridges bun:sqlite → better-sqlite3 API
loadDatabase() (db-base.ts:117-138) already has runtime detection (Bun vs Node)
SQLiteBase provides a clean abstract base that doesn't depend on better-sqlite3 directly
better-sqlite3 is already declared as an optionalDependency, not a hard requirement
Suggested approach
Add a node:sqlite adapter (similar to BunSQLiteAdapter) for Node.js >= 22.5:
loadDatabase() priority:
1. Bun runtime → bun:sqlite (existing BunSQLiteAdapter)
2. Node >= 22.5 → node:sqlite (new NodeSQLiteAdapter) ← NEW
3. Node < 22.5 → better-sqlite3 (existing, fallback)
node:sqlite is built into the Node.js binary — no separate .node file, no dlopen(), no .got.plt to corrupt. It supports the same synchronous API pattern that context-mode uses.
Alternatively: user-configurable backend
Allow users to specify their preferred backend via environment variable or plugin config:
CONTEXT_MODE_SQLITE_BACKEND=node # use node:sqlite
CONTEXT_MODE_SQLITE_BACKEND=bun # use bun:sqlite
CONTEXT_MODE_SQLITE_BACKEND=native # use better-sqlite3 (default)
API compatibility notes
The following better-sqlite3 APIs are used by context-mode and would need adapter coverage:
| API |
Used For |
node:sqlite equivalent |
prepare(sql) |
Statement caching |
db.prepare(sql) |
stmt.run/get/all() |
CRUD operations |
Same API names |
exec(sql) |
Schema DDL |
db.exec(sql) |
pragma(str) |
WAL, checkpoints |
db.exec('PRAGMA ...') |
transaction(fn) |
Atomic writes |
Manual BEGIN/COMMIT wrapper |
FTS5 MATCH, bm25(), highlight() |
Full-text search |
Same (SQLite feature, not library feature) |
FTS5 is a SQLite extension, not a better-sqlite3 feature — it works with any SQLite binding that ships a complete SQLite build.
Environment
- OS: Ubuntu 24.04, Linux 6.19.10
- Arch: AMD x86-64
- Node: v22.22.2 / v24.14.1 (via nvm)
- context-mode: v1.0.74
- better-sqlite3: v12.8.0
- RAM: 13 GiB (4 GB swap used — increases V8 GC pressure → more madvise collisions)
References
Problem
context-modecrashes intermittently with SIGSEGV (Signal 11) when running on Node.js v22/v24 on Linux due to a V8 runtime bug that corruptsbetter-sqlite3's native addon.got.pltsection.Root cause
V8's garbage collector calls
madvise(MADV_DONTNEED)on memory ranges that can overlapbetter_sqlite3.node's writable ELF segments (.got.plt). This discards resolved symbol addresses on Copy-on-Write pages, restoring unrelocated on-disk offsets — causing function calls to jump to near-null addresses.Upstream issue: nodejs/node#62515 — "Sporadic SIGSEGV: native addon .got.plt reset to unrelocated file offsets"
Why context-mode is especially affected
better-sqlite3calls for FTS5 indexing and searchCrash frequency
All coredumps show the same pattern: frame #0 at near-null address (0x12xxx range), consistent with
.got.pltcorruption.What doesn't help
LD_BIND_NOW=1(eager symbol resolution)LD_PRELOADmadvise guard (intercept+block on .node segments)The only reliable fix is eliminating the separate
.nodebinary that getsdlopen()'d as a standalone ELF file.Proposal: Support pluggable SQLite backends
The codebase already has the right abstraction for this:
BunSQLiteAdapter(db-base.ts:40-104) already bridgesbun:sqlite→ better-sqlite3 APIloadDatabase()(db-base.ts:117-138) already has runtime detection (Bun vs Node)SQLiteBaseprovides a clean abstract base that doesn't depend on better-sqlite3 directlybetter-sqlite3is already declared as anoptionalDependency, not a hard requirementSuggested approach
Add a
node:sqliteadapter (similar toBunSQLiteAdapter) for Node.js >= 22.5:node:sqliteis built into the Node.js binary — no separate.nodefile, nodlopen(), no.got.pltto corrupt. It supports the same synchronous API pattern that context-mode uses.Alternatively: user-configurable backend
Allow users to specify their preferred backend via environment variable or plugin config:
API compatibility notes
The following better-sqlite3 APIs are used by context-mode and would need adapter coverage:
prepare(sql)db.prepare(sql)stmt.run/get/all()exec(sql)db.exec(sql)pragma(str)db.exec('PRAGMA ...')transaction(fn)BEGIN/COMMITwrapperMATCH,bm25(),highlight()FTS5 is a SQLite extension, not a better-sqlite3 feature — it works with any SQLite binding that ships a complete SQLite build.
Environment
References
node:sqlitedocs — built-in SQLite module