Repository navigation
Closed
Labels
app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)Package/app: mcpx (pkgs/ or apps/ in this repo)effort/xsTrivial: expected under 30 minutes of workTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)Something isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientNice to have; do when convenientsource/pr-diff-reviewFiled by the pr-diff-review jobFiled by the pr-diff-review jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted testsQueue packet kind: bounded fix with reproduction and targeted tests
Description
Finding
daemon.Server.taskStore() (pkgs/mcpx/internal/daemon/ops.go, current main 77918e0f) opens the durable SQLite task store and drops the error unconditionally:
if s.paths.State != "" {
dbPath := filepath.Join(s.paths.State, "tasks.db")
if store, err := tasks.Open(dbPath); err == nil {
s.tasks = store
}
}
if s.tasks == nil {
s.tasks = tasks.New() // in-memory fallback, no log, no record
}There is no log call anywhere in the function. The daemon has a logger and uses it for exactly this kind of degradation elsewhere (pkgs/mcpx/internal/daemon/server.go: opts.Logger.Printf("elicitation disabled: %v", berr)), but a failed task-store open is completely silent. Because creation is sync.Once, the fallback is also sticky for the life of the process: a transient failure at first use downgrades the daemon permanently, with no retry.
Evidence
- PR: mcpx: one durable task store across MCP and /v1 — Phase 1 of #1554 (#1555) #1575 (merged, commits
508fb8be,516df392) — "one durable task store across MCP and /v1, Phase 1 of design(mcpx): tasks, finished — one task store for MCP and /v1, and a client that can call task-required tools #1554". It wired this store into the MCP surface (internal/cli/root.go:a.daemonStore = srv.TaskStore(), called eagerly at daemon startup;internal/cli/serve.go:srv.TaskStore = a.daemonStore) and closed the conformance gapext-tasks-durable-before-responseinpkgs/mcpx/docs/spec/conformance-matrix.mdon the strength of this store ("the task store is an in-memory map; a task does not survive the daemon" → now marked tested viaTestInjectedStoreKeepsMCPTasksAcrossReopen). tasks.Open(pkgs/mcpx/internal/tasks/tasks.go:148-166) returns real errors:os.MkdirAllfailure on the state dir,initDBschema-exec failure, andloadTasksFromDBquery failure — i.e. an unwritable state directory or a corrupttasks.dbboth reach the silent branch.- Verified on current main
77918e0f(2026-10-28): the function is byte-identical; no logging, no metric, no status surface records the fallback. Deduped against open + closed issues 2026-10-28: no issue covers this fallback (the silent in-memory fallback for/v1predates mcpx: one durable task store across MCP and /v1 — Phase 1 of #1554 (#1555) #1575; mcpx: one durable task store across MCP and /v1 — Phase 1 of #1554 (#1555) #1575 is what extended it to MCP tasks and based a conformance closure on it).
Why it matters
When the open fails, three things go wrong at once, all invisibly:
- Every task already persisted in
tasks.dbbecomes unreachable — the daemon never opened the file, so MCP and/v1both report those tasks as unknown. - Every new task is memory-only and evaporates on daemon restart — precisely the failure the conformance matrix now says is covered.
- Nobody can diagnose it: no log line names the path or the error, so the symptom ("tasks disappeared") has no on-box evidence trail.
Acceptance criteria
- A failed
tasks.OpenintaskStore()is logged once via the daemon logger (s.logger), naming the db path and the underlying error, before the in-memory fallback is installed. - A regression test pins it: a daemon server whose
tasks.dbcannot be opened (e.g. corrupt file contents or an unusable state path) falls back and emits the log line; the successful-open path stays silent-or-unchanged and still returns the one shared store instance. - The fallback remains a fallback (daemon keeps serving) — this issue asks for visibility, not a hard failure.
- Existing task-store tests keep passing (
internal/daemon/taskstore_shared_test.go,internal/mcpserver/tasks_shared_store_test.go).
Metadata
Metadata
Assignees
Labels
app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)Package/app: mcpx (pkgs/ or apps/ in this repo)effort/xsTrivial: expected under 30 minutes of workTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)Something isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientNice to have; do when convenientsource/pr-diff-reviewFiled by the pr-diff-review jobFiled by the pr-diff-review jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted testsQueue packet kind: bounded fix with reproduction and targeted tests
Activity
developing-today commentedon Oct 28, 2026
CODE-928
dezren39 commentedon Oct 28, 2026
🤖 Agent note · filed
13 remaining items
dezren39 commentedon Nov 1, 2026
🤖 Agent note · done
tasks.Openfailures before the unchanged in-memory fallback.6fd77b9c9; task 5067 completed aspr_opened.user/reviewmarks the handoff while CI runs. The PR is authored by dezren39 (Drewry Pope), so this lane will not modify or merge it.dezren39 commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as small_fix at priority 50 (priority/low). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 4, 2026
🤖 Agent note · done (already fixed at current main)
tasks.Openfailures in daemontaskStore()before the in-memory fallback.4291001ba484e20af72f5cafdc1f461122c6f892.mainpkgs/mcpx/internal/daemon/ops.golines 600–602:s.logger.Printf("task store: could not open %s: %v; using in-memory fallback", dbPath, err)insidetaskOnce(so once), befores.tasks = tasks.New()fallback (fallback unchanged, daemon keeps serving). Regression testpkgs/mcpx/internal/daemon/taskstore_open_fallback_test.go(TestTaskStoreOpenFailureLogsAndKeepsFallbackUsable) is on main: pins log count = 1 with path + error, fallback usable, and the shared instance retained. PR fix(mcpx): log task store open fallback #4055 body records daemon / tasks / injected-store MCP tests passing before merge.