You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Interrupted bulk-load recovery can be repeatedly watchdog-killed while rebuilding indexes #1887
Opening a database after an interrupted bulk load rebuilds every missing
secondary index synchronously on the main thread. If one CREATE INDEX
exceeds the liveness-watchdog window, startup is killed before that index
commits and every restart repeats the same recovery failure.
Context
Issue #1556 and PR #1562 added open-time restoration of indexes left missing
by an interrupted bulk load. The recovery is correct, but healBulkSecondaryIndexes() executes the complete DDL sequence synchronously.
PR #1323 previously measured four edge-index builds taking 79 seconds and made
the normal bulk-load completion path watchdog-safe. The crash-recovery path
still performs parse, reference, and edge index recreation without yielding or
moving the work off-thread.
Disk-progress deferral is insufficient when an individual CREATE INDEX
produces no committed DB/WAL change before the timeout. The watchdog's hard cap
can also terminate longer recovery despite intermediate disk activity.
A scaled reproduction using the real watchdog:
Populate 300,000 nodes and leave the bulk-parse indexes dropped.
Start recovery with the database and WAL configured as progress paths.
Set CODEGRAPH_WATCHDOG_TIMEOUT_MS=20.
Call DatabaseConnection.open().
Two consecutive processes were killed during the same recovery path. This uses
the repository's established lowered-timeout technique for validating watchdog
failure modes.
Acceptance Criteria
Interrupted bulk-load recovery restores every required secondary index.
Watchdog-supervised asynchronous opens keep the event loop responsive
throughout index recreation.
The database is not exposed for normal queries until recovery completes.
Healthy opens retain their existing low-overhead fast path.
Regression coverage exercises recovery under a real lowered watchdog.
Existing synchronous API behavior remains compatible.
The fix is documented under the Unreleased changelog.
Technical Notes
The existing off-thread SQLite maintenance pattern provides precedent. The fix
should preserve the watchdog threshold rather than weakening or disabling it.
Additional Windows field evidence: ~14–16 GiB MCP-process memory spikes with an incomplete large index
Adding measured field evidence that appears consistent with this issue, including the memory-pressure impact. This is a source/state correlation, not a captured runtime stack proving which CREATE INDEX was executing.
Environment
CodeGraph 1.6.0, official npm Windows x64 distribution (@colbymchenry/codegraph and @colbymchenry/codegraph-win32-x64).
Windows 11 25H2, build 26200.9457, x64, approximately 32 GiB RAM.
MCP subprocess launched by the Codex desktop/app-server, with codegraph serve --mcp and no explicit --path.
Measurements collected on 2026-10-05. No termination, configuration change, upgrade or index rebuild was performed during this investigation.
The same live process repeatedly changed size
Windows process counters showed the following for one continuously running CodeGraph node.exe process; its PID and creation time stayed unchanged:
Relative sample time
Private committed memory
Working set
0:00
14.46 GiB
14.07 GiB
1:52
1.41 GiB
1.30 GiB
3:05
5.92 GiB
5.68 GiB
12:06
13.80 GiB
13.45 GiB
17:18
15.61 GiB
15.24 GiB
At the last sample, system committed memory was 43,093,766,144 / 43,892,195,328 bytes (~98.2%), with about 3,000 MiB available physical memory. The affected process had been alive for over seven hours.
This is user-mode CodeGraph memory, not the separate Windows NtFC kernel-pool problem: NtFC nonpaged bytes stayed around 58,672 bytes, and total nonpaged pool was about 1 GiB. The substantial drop and subsequent regrowth also mean these observations alone do not establish an unreclaimable memory leak.
Read-only database and process inspection
A read-only process-directory probe identified the large workspace as this process's working directory. Duplicated file-handle inspection confirmed that it actually held the large workspace's codegraph.db, WAL and SHM open. The same process also held a second, small healthy project's database open.
The large default workspace includes repository snapshots and third-party source corpora:
Main database: 14,978,273,280 bytes (~13.95 GiB).
files: 174,369 rows.
nodes: 2,823,016 rows.
unresolved_refs: 11,200,451 rows.
project_metadata.index_state: indexing, last updated 2026-09-29.
All three FTS maintenance triggers were present.
The following nine required secondary indexes were absent in two inspections several minutes apart:
For comparison, the second open database was only 16,846,848 bytes, had 133 file rows, state complete, and all these indexes present.
Database observations used SQLite URI mode=ro, PRAGMA query_only=ON and bounded query execution; they did not open the database through CodeGraph's healing path.
Recovery / watchdog evidence
The large workspace's existing daemon log contains repeated daemon starts followed by:
Main thread unresponsive for ~60s — killing the wedged process so a fresh one can start (#850).
This pattern recurred across multiple days. In the latest inspected pair, the daemon started and was watchdog-terminated about 60 seconds later.
Inspection of the installed 1.6.0 implementation, rather than assuming current main matches it, found:
That method loops over the required indexes and executes each missing CREATE INDEX via synchronous db.exec, without yielding.
Connection configuration sets temp_store = MEMORY; its configured page cache is only about 64 MB and mmap is 256 MB.
The MCP proxy can fall back to a local in-process engine and replay in-flight calls when the shared daemon disappears. That is a possible amplification path; the exact fallback event for the high-memory process was not separately captured.
These conditions strongly match interrupted-index recovery, with a very large corpus amplifying its memory and I/O cost. However, no live CPU/heap stack or SQLite statement trace was collected, so attribution of each observed memory peak to a particular rebuild/sort remains a hypothesis.
Could recovery validation include memory peaks on a large incomplete graph, in addition to watchdog liveness, and whether daemon-loss fallback can cause multiple clients to independently repeat recovery? PR #1888 appears relevant; this report does not claim that a released version already fixes this case.
Only this sanitized summary is shared: no usernames, absolute local paths, project names, raw logs, screenshots, database files or dumps are attached.
Activity
Merge codex/integration-all-2026-09-26 (colbymchenry#1959, colbymchen…
WQMYH commentedon Oct 5, 2026
Additional Windows field evidence: ~14–16 GiB MCP-process memory spikes with an incomplete large index
Adding measured field evidence that appears consistent with this issue, including the memory-pressure impact. This is a source/state correlation, not a captured runtime stack proving which CREATE INDEX was executing.
Environment
@colbymchenry/codegraphand@colbymchenry/codegraph-win32-x64).codegraph serve --mcpand no explicit--path.The same live process repeatedly changed size
Windows process counters showed the following for one continuously running CodeGraph
node.exeprocess; its PID and creation time stayed unchanged:At the last sample, system committed memory was 43,093,766,144 / 43,892,195,328 bytes (~98.2%), with about 3,000 MiB available physical memory. The affected process had been alive for over seven hours.
This is user-mode CodeGraph memory, not the separate Windows NtFC kernel-pool problem: NtFC nonpaged bytes stayed around 58,672 bytes, and total nonpaged pool was about 1 GiB. The substantial drop and subsequent regrowth also mean these observations alone do not establish an unreclaimable memory leak.
Read-only database and process inspection
A read-only process-directory probe identified the large workspace as this process's working directory. Duplicated file-handle inspection confirmed that it actually held the large workspace's
codegraph.db, WAL and SHM open. The same process also held a second, small healthy project's database open.The large default workspace includes repository snapshots and third-party source corpora:
files: 174,369 rows.nodes: 2,823,016 rows.unresolved_refs: 11,200,451 rows.project_metadata.index_state: indexing, last updated 2026-09-29.For comparison, the second open database was only 16,846,848 bytes, had 133 file rows, state complete, and all these indexes present.
Database observations used SQLite URI
mode=ro,PRAGMA query_only=ONand bounded query execution; they did not open the database through CodeGraph's healing path.Recovery / watchdog evidence
The large workspace's existing daemon log contains repeated daemon starts followed by:
This pattern recurred across multiple days. In the latest inspected pair, the daemon started and was watchdog-terminated about 60 seconds later.
Inspection of the installed 1.6.0 implementation, rather than assuming current main matches it, found:
DatabaseConnection.open()synchronously invokeshealBulkSecondaryIndexes().CREATE INDEXvia synchronousdb.exec, without yielding.temp_store = MEMORY; its configured page cache is only about 64 MB and mmap is 256 MB.These conditions strongly match interrupted-index recovery, with a very large corpus amplifying its memory and I/O cost. However, no live CPU/heap stack or SQLite statement trace was collected, so attribution of each observed memory peak to a particular rebuild/sort remains a hypothesis.
Could recovery validation include memory peaks on a large incomplete graph, in addition to watchdog liveness, and whether daemon-loss fallback can cause multiple clients to independently repeat recovery? PR #1888 appears relevant; this report does not claim that a released version already fixes this case.
Only this sanitized summary is shared: no usernames, absolute local paths, project names, raw logs, screenshots, database files or dumps are attached.
Phase 2: reliability and crash safety