mirror of
https://github.com/DamieMoon/ctx.git
synced 2026-10-17 09:59:38 +02:00
Query 500 after 120 s: synchronous embed backfill in the request path has no time budget #1
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Observed
Fresh install (ctx.damienmoon.sh, build
38fdb74f, v5.21.1). Firstctx queryafter saving a ~33 kB block (≈10k tokens) fails with HTTP 500 after exactly 120 s. The synthesis backend (Haiku via ctx-shim) is not involved — the translation step completed in 1.4 s.Server log (request
c271f3b0203621c2):ctx-embed (Qwen3-Embedding-8B-Q8_0, CPU,
--threads 16, recommended f16/kv-unified config from docs/operations.md) processes at ~28 tok/s:A 10k-token block therefore needs ~6 min to embed; the request deadline is 120 s.
Why this is more than a tuning problem
QueryHandler.backfillPending(go/internal/handler/query.go:1710, called at:832) runs the pending-embedding backfill synchronously inside the request, bounded only byembed_backfill.sync_cap(count of blocks, default 4) — not by time. Consequences on a slow embed backend:embedcache: admission: context canceled), so the query fails with 500 instead of degrading to search-without-that-block.wireclass → finite backoff (60 s · 2ⁿ, cap 24 h). Until the scheduler arm (backfillOneEmbedding) succeeds in the background, every query that lands while the memo has expired repeats the 120 s failure.wireis meant to signal "backend down". Here the backend is healthy, just slow relative to the caller's deadline — a caller-timeout class with "leave it to the background arm" semantics would avoid the repeated 120 s burns.The code comment acknowledges the shape ("the known lopsidedness (an unbounded backfill loop ahead of the search) is NOT solved here, only honestly classified").
Suggested direction
sync_cap, and reserve the remainder for the question embed + search. A block that does not fit the budget is left to the scheduler arm, not attempted.wire; either skip without a memo or use a dedicated class with a short fixed backoff so the background arm picks it up at once.Side note
query.go:732logsgerman detected, translatingfor a Swedish question. Harmless (translation to English is correct), but the detector label is misleading.Deployment side (separate, not a ctx bug)
--threads 16on a 48-core host; raising it is the cheap local fix. Long-term the docs already say embeddings belong on a GPU.