Problem
brainbar_hybrid_helper wedges to 100% of one core and stays there until killed. Observed three
times on 2026-08-24 alone: 19:04, 19:20, 20:14 — roughly every 15–20 minutes, unprompted. The
first instance had burned 46m12s of CPU across ~7h of life.
Evidence it is a wedge, not load
SIGTERM the wedged process and BrainBar respawns it against the same DB and the same client
traffic — the replacement measures 0% CPU. Same code, same load, 100% → 0%. A loaded process
would not do that.
sample <pid> 5 puts 4150/4150 busy-thread samples in sqlite3_step → sqlite3VdbeExec, dominated
by sqlite3VdbeMemSetText / sqlite3VdbeMemGrow (row-by-row text materialization) plus
sqlite3BtreeIndexMoveto, with no fts5 symbols anywhere in the hot path. That is a scan over
chunks (1.07M rows / 14.8 GB), not an FTS hit or an index seek.
What PR #735 does and does not do
#735 adds a hard request deadline so a wedged query can no longer peg a core indefinitely — it logs
the offending request and recycles the process. That is containment, not a cure. This issue tracks
the remaining work: identify the actual query.
Two real leads (neither proven to be this wedge — do not assume)
src/brainlayer/mcp/search_repo.py:2117 —
fts_timeout_ms = _BRAINBAR_HELPER_FTS_BUDGET_MS if brainbar_helper_fast_profile else None.
FTS is bounded only for the BrainBar fast profile; every other caller runs FTS unbounded.
search_repo.py:2266 — the trigram fetch is the one _fetch_fts_rows call that passes no
timeout_ms at all, while its siblings on :2263/:2265 do.
⚠️ Constraint for whoever takes this
_fetch_fts_rows returns [] on timeout. So "just add timeouts everywhere" would silently drop
search results, which BrainLayer forbids. Fix the unboundedness without introducing silent
truncation — #735 deliberately fails loudly for this reason.
Acceptance criteria
- The wedging statement is identified with evidence (not inferred).
- It is bounded or made index-satisfiable without silently truncating results.
- The helper survives 24h under normal fleet traffic with no 100%-core episode.
— brainlayerClaude (lead) · claude-code/claude-opus-5
Problem
brainbar_hybrid_helperwedges to 100% of one core and stays there until killed. Observed threetimes on 2026-08-24 alone: 19:04, 19:20, 20:14 — roughly every 15–20 minutes, unprompted. The
first instance had burned 46m12s of CPU across ~7h of life.
Evidence it is a wedge, not load
SIGTERM the wedged process and BrainBar respawns it against the same DB and the same client
traffic — the replacement measures 0% CPU. Same code, same load, 100% → 0%. A loaded process
would not do that.
sample <pid> 5puts 4150/4150 busy-thread samples insqlite3_step → sqlite3VdbeExec, dominatedby
sqlite3VdbeMemSetText/sqlite3VdbeMemGrow(row-by-row text materialization) plussqlite3BtreeIndexMoveto, with no fts5 symbols anywhere in the hot path. That is a scan overchunks(1.07M rows / 14.8 GB), not an FTS hit or an index seek.What PR #735 does and does not do
#735 adds a hard request deadline so a wedged query can no longer peg a core indefinitely — it logs
the offending request and recycles the process. That is containment, not a cure. This issue tracks
the remaining work: identify the actual query.
Two real leads (neither proven to be this wedge — do not assume)
src/brainlayer/mcp/search_repo.py:2117—fts_timeout_ms = _BRAINBAR_HELPER_FTS_BUDGET_MS if brainbar_helper_fast_profile else None.FTS is bounded only for the BrainBar fast profile; every other caller runs FTS unbounded.
search_repo.py:2266— the trigram fetch is the one_fetch_fts_rowscall that passes notimeout_msat all, while its siblings on:2263/:2265do._fetch_fts_rowsreturns[]on timeout. So "just add timeouts everywhere" would silently dropsearch results, which BrainLayer forbids. Fix the unboundedness without introducing silent
truncation — #735 deliberately fails loudly for this reason.
Acceptance criteria
— brainlayerClaude (lead) · claude-code/claude-opus-5