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
gateway: indexing blocks the event loop — /health and all routes stop responding during grammar download and import pre-scan #1745
Once jobs run (see #1744), indexing a repository whose grammars are not cached makes the
whole gateway unresponsive, including /health. Without internet access every download attempt
blocks for 60 s (tree-sitter-language-pack's HTTP timeout), and CGC retries it for every file, so
a liveness probe kills the process. With grammars present, the synchronous phases still block the
loop for seconds per repository.
Cause
run_tree_sitter_index_async calls pre_scan_for_imports(...) synchronously on the loop
(tools/indexing/pipeline.py L124; also scip_pipeline.py L110 and L285). The pre-scan builds
parsers via get_parser → TreeSitterParser → get_language_safe → tree_sitter_language_pack.get_language, which downloads the platform bundle from GitHub on
a cache miss.
The first parser init always calls get_language('python') (utils/tree_sitter_manager.py L58),
whatever language the repo uses.
A failed parser init is not cached (get_parser, graph_builder.py L142-146), so the download is
retried for each pre-scan extension and then for each file. Locally, with a silent endpoint, a
1-file repo froze the loop for 120 s and a 3-file repo for 240 s. Both jobs ended completed
with no definitions.
Even with grammars present, discovery, the import pre-scan and all post-processing/graph writes
(pipeline.py L271-420) run on the loop. The pre-scan alone took 3–6 s for a repo with 371
Python files.
Environment
codegraphcontext 0.6.13 (same on main), tree-sitter-language-pack 1.20.0, Python 3.12, Linux
container without internet egress.
Suggestions
Run the pre-scan (and ideally the post-processing phases) via asyncio.to_thread.
Before the pre-scan, call tree_sitter_language_pack.prefetch(langs) in a
thread. It releases the GIL: in the same test the loop's largest gap was 0.05 s. Remember a
failed grammar so it is not retried for every file.
Offline deployments: document fetching grammars at build time with prefetch([...]) or the
release bundle (download([...]) is currently a no-op, see bug: download([...]) is a no-op for known languages and returns the requested count xberg-io/tree-sitter-language-pack#201), and a TREE_SITTER_LANGUAGE_PACK_MANIFEST_URL that refuses connections (e.g. a closed local port)
so a missing grammar fails immediately. A blackholed address still waits 60 s. A cached manifest.json overrides MANIFEST_URL.
Disclosure: the investigation and this report were prepared with AI assistance (Claude Code) and reviewed by a human before posting.
#1761 removes the unrelated Python grammar probe and stops hollow graphs from reporting success, but does not solve the gateway responsiveness issue. Remaining acceptance: a deterministic /health responsiveness test during uncached grammar loading, GIL-releasing grammar prefetch, and offloading synchronous discovery/import pre-scan/post-processing. Keeping this separate and open.
Published #1763 for the gateway-liveness work, stacked on the parser-initialization fix #1761. It moves Tree-sitter discovery, pre-scans, resolution and graph-write phases to workers, and runs blocking SCIP CLI/augmentation work in one worker. The language loader uses language-pack's GIL-releasing prefetch before get_language; the upstream v1.20.0 binding confirms that distinction. New tests call the real /health route while indexing phases are deliberately blocked, and cover cold-fetch failure without per-file retries plus cooperative SCIP cancellation. Parser/API/indexing regressions pass 520 tests; graph-write/resilience/convergence regressions pass 64 with 1 skip. Main-target CI and independent approval are still needed after #1761 merges. This does not provide rollback or interruption of an in-flight native write (#829), so those cancellation guarantees remain separate.
#1763 targeted its dependency branch; #1765/#1766 carry the same liveness changes onto main. Blocking discovery/pre-scan/SCIP/write phases move to workers, with sequential writes and documented native-call cancellation limits.
Activity
github-actions commentedon Sep 29, 2026
Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ
Shashankss1205 commentedon Oct 9, 2026
#1761 removes the unrelated Python grammar probe and stops hollow graphs from reporting success, but does not solve the gateway responsiveness issue. Remaining acceptance: a deterministic /health responsiveness test during uncached grammar loading, GIL-releasing grammar prefetch, and offloading synchronous discovery/import pre-scan/post-processing. Keeping this separate and open.
Shashankss1205 commentedon Oct 9, 2026
Published #1763 for the gateway-liveness work, stacked on the parser-initialization fix #1761. It moves Tree-sitter discovery, pre-scans, resolution and graph-write phases to workers, and runs blocking SCIP CLI/augmentation work in one worker. The language loader uses language-pack's GIL-releasing prefetch before get_language; the upstream v1.20.0 binding confirms that distinction. New tests call the real /health route while indexing phases are deliberately blocked, and cover cold-fetch failure without per-file retries plus cooperative SCIP cancellation. Parser/API/indexing regressions pass 520 tests; graph-write/resilience/convergence regressions pass 64 with 1 skip. Main-target CI and independent approval are still needed after #1761 merges. This does not provide rollback or interruption of an in-flight native write (#829), so those cancellation guarantees remain separate.
Shashankss1205 commentedon Oct 15, 2026
Maintenance review — 15 October 2026
#1763 targeted its dependency branch; #1765/#1766 carry the same liveness changes onto main. Blocking discovery/pre-scan/SCIP/write phases move to workers, with sequential writes and documented native-call cancellation limits.