Skip to content

mcpx: /v1/chat/completions panics on schema-built settings (proxy.* paths undeclared) #2726

Closed

Description

@dezren39

Found while dispositioning Codex findings on PR #2711 (task 3271). Pre-existing on main, unrelated to #1975.

Claim: handleChatCompletions (pkgs/mcpx/internal/daemon/routes_proxy.go) panics with settings: no such setting proxy.maxTools whenever the daemon has a non-nil settings set built from the registry schema.

Evidence:

  • The handler reads three undeclared paths: s.set.Int("proxy.maxTools") (:63), s.set.String("proxy.upstreamUrl") (:137), s.set.String("proxy.apiKey") (:148). All three lines pre-date mcpx: optional bearer token for /v1 and /mcp #1975 (untouched since migration commit a03494f).
  • No proxy.* path is declared anywhere under pkgs/mcpx/internal/settings/ (checked every Path: declaration; only transport.*, upstream.*, retention.*, etc. exist).
  • Typed readers panic on unknown paths by design (internal/settings/value.go: raw() panics settings: no such setting).
  • Reproduced: a settings.New(settings.Registry()) set + handleChatCompletions panics at proxy.maxTools (observed in a new test for mcpx: optional bearer-token auth for /v1 and /mcp (#1975) #2711, which works around it via WithOverrides).
  • Every production set construction found (daemon/server.go:212, cli/*) uses settings.Registry(), so a real daemon serving /v1/chat/completions should hit this. Existing unit tests dodge it by using &Server{reg: reg} with a nil set.

Suggested fix (triage to confirm production impact first): declare the proxy.* family in the settings registry (with env bindings, matching the OPENAI_* fallbacks), or make the handler tolerant of undeclared paths. Not fixed in #2711 — out of scope there.

Acceptance criteria

  • Production impact is confirmed or refuted with evidence: a daemon built from the registry schema serving POST /v1/chat/completions either reproduces the settings: no such setting proxy.maxTools panic or is shown not to reach the undeclared reads.
  • The fix lands: the proxy.* settings family (proxy.maxTools, proxy.upstreamUrl, proxy.apiKey) is declared in the settings registry with env bindings matching the OPENAI_* fallbacks, or the handler no longer panics on undeclared paths — with the choice justified on this issue.
  • A regression test exercises handleChatCompletions with a schema-built settings set (not a nil set) and passes.
  • Existing mcpx settings/daemon tests still pass in CI.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)
    priority/highImportant and time-sensitive
    effort/sSmall: expected under 2 hours of work
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 30, 2026
  2. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Intake review

    🤖 Agent note · handed off

    Related: PR #2711 / issue #1975 (where this was found while dispositioning Codex findings — explicitly out of scope there, pre-existing since migration commit a03494f). Also in the same family as the settings-registry failures in #2716 / #2697 (undeclared/missing settings paths on main), though those are test failures, not this panic.

    Still live? Yes — the evidence is file:line on current main (routes_proxy.go:63,137,148 reading undeclared proxy.* paths; no proxy.* declaration under internal/settings/; typed readers panic by design at value.go), plus a reproduction with a schema-built set. No merged PR claims this fix.

    Notes / risks: Every production set construction found uses settings.Registry(), so the route is very likely broken for real daemons while unit tests (nil set) stay green — a coverage-shape problem as much as a missing declaration. If triage instead makes the handler tolerant of undeclared paths, that weakens the registry's panic-by-design contract for every other caller; declaring the family is the narrower fix.

    Suggested approach: Confirm production reachability first (one schema-built daemon request), then declare proxy.* with env bindings matching the existing OPENAI_* fallbacks, and add the handler test with a real registry-built set.

    Labels normalised this pass: priority/high (a public daemon route panics on the production settings construction), effort/s, status/needs-triage, meta/enriched (kind/bug and app/mcpx were already present). An ## Acceptance criteria section was appended to the body (original preserved verbatim above it).

  3. added
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  4. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    agent-note:v1
    state: reviewed (coverage loop-back)
    Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7352 (triage, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
    Found via: coverage loop-back 2026-11-03

  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  6. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    Triage findings — task 7352 (lane code-g)

    Verdict: production impact CONFIRMED for the pre-fix code, but the fix has already landed on main — this issue is already done.

    Verified fresh against origin/main @ 6aeb038a0cd64b5057912edac71d4c2744a8b5d6 (2026-11-03 17:39 -0600):

    • Pre-fix claim was accurate: the handler read proxy.maxTools / proxy.upstreamUrl / proxy.apiKey through the typed readers (Set.Int/Set.String), whose raw() panics settings: no such setting <path> on undeclared paths (pkgs/mcpx/internal/settings/value.go), none of the three paths is declared in the registry, and production construction builds the set from the schema (pkgs/mcpx/internal/daemon/server.go: settings.New(settings.Registry())).
    • Fix landed in PR mcpx(daemon): bound chat proxy upstream calls (#2114) #3380 (fix(mcpx): bound chat proxy upstream calls, for mcpx(daemon): chat-completions proxy has no upstream timeout and buffers the whole upstream response in memory — proxyToUpstream uses http.DefaultClient and an uncapped TeeReader buffer #2114), commit a98c6941f3e5fdcf88670284d4b353e9599f774b on main (2026-11-03 15:41 -0600) — after this issue was filed (2026-10-30) and after its last review note (2026-11-03 16:47 UTC).
    • The fix takes the acceptance criteria's alternative branch — the handler no longer panics on undeclared paths: pkgs/mcpx/internal/daemon/routes_proxy.go now reads all three via the tolerant s.set.Value(path) with an ok check (:92-93, :168-169, :181-182), falling back to defaults / OPENAI_* env vars exactly as before. The one remaining typed read in the handler, proxy.timeout (:280-281), IS declared (pkgs/mcpx/internal/settings/proxy.go, added by the same commit).
    • Regression coverage: TestProxyUpstreamTimeoutReturnsBadGateway (routes_proxy_test.go) drives handleChatCompletions with a schema-built set (settings.New(settings.Registry()), only proxy.timeout overridden) — the three undeclared reads take the ok=false path with no panic and the handler returns 502 as asserted. PR mcpx(daemon): bound chat proxy upstream calls (#2114) #3380 also added pkgs/mcpx/internal/e2e/proxy_test.go and settings/proxy_test.go.

    Residual (cosmetic, not blocking): the NOTE comment in routes_proxy_test.go (~:109) still says a schema-built set "panics on the typed readers in handleChatCompletions — filed as a follow-up"; that text is stale since a98c694 and can be corrected whenever that test is next touched.

    Closing as already done per the evidence above. Queue task 7352 completes already_done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)meta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/highImportant and time-sensitivesource/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions