Skip to content

bug(runtime): recurring boot noise — dead MCP timeouts, Invalid port preconnect, N-way usage polling #162

Open

Description

@devswha

Four recurring warnings/debug failures fire on every CLI boot and every polling cycle. Individually minor, together they are 100% of today's warn volume and they hide real signal.

Evidence

~/.gjc/logs/gjc.2026-09-17.log, 186 lines, debug 169 / warn 17 / error 0. All 17 warns:

14×  GJC plugin MCP connect failed
      path=mcp:stylegallery           error=MCP server connection timed out during startup
      path=mcp:stylegallery-material  error=MCP server connection timed out during startup
 2×  Extension command 'notify' from <inline-0> conflicts with built-in commands. Skipping.
 1×  sdk broker reaped a session registration whose host process is gone

1. MCP startup timeouts — 82% of all warnings

stylegallery and stylegallery-material time out during startup on every single boot. Either they are dead and should be removed from marketplaces.json/plugin config, or the startup timeout is too tight and should be raised. Right now the cost is a guaranteed pair of warnings per process launch, forever.

2. Invalid port on model-host preconnect

{"level":"debug","message":"Model-host preconnect failed",
 "baseUrl":"https://api.anthropic.com","error":"Invalid port"}

https://api.anthropic.com has no port component. Something is parsing an empty port as invalid rather than defaulting to 443. The preconnect optimization silently never runs for the primary provider.

3. Duplicate usage polling across processes

01:35:02.289  pid=16093  Usage fetch requested  providers=[anthropic, google-antigravity, kimi-code, openai-codex]
01:35:02.289  pid=56360  Usage fetch requested  providers=[anthropic, google-antigravity, kimi-code, openai-codex]
01:35:02.290  pid=16093  Usage fetch queued    google-antigravity …
01:35:02.290  pid=56360  Usage fetch queued    google-antigravity …
… (both PIDs queue all 5 credentials, same second)
01:35:02.872  pid=56360  Usage fetch resolved  [5 reports]
01:35:04.565  pid=16093  Usage fetch resolved  [5 reports]

Every concurrent process polls all providers on the same schedule. With N processes running this is N× the provider API calls for identical data, including OAuth-backed endpoints. Three gjc processes were live at the time of capture.

4. Local model discovery failures logged every boot

model discovery failed for provider  llama.cpp   http://127.0.0.1:8080/    Unable to connect.
model discovery failed for provider  lm-studio   http://127.0.0.1:1234/v1  Unable to connect.
model discovery failed for provider  omlx        http://127.0.0.1:8080/v1  Unable to connect.

Expected when those servers are not running. Fine at debug, but combined with the above the boot log is mostly known-failure noise.

Expected

  • Drop or fix the two dead MCP entries; alternatively make a startup timeout a one-time warning rather than per-attempt.
  • Default the port when the URL omits it, so anthropic preconnect actually works.
  • Share usage-fetch results across processes (cache in agent.db, or elect one poller) instead of N× fan-out.
  • Resolve the notify extension command name collision rather than skipping it each boot.

Activity

  1. devswha commented on Sep 16, 2026

    @devswha
    OwnerAuthor

    Checked where each of the four actually originates. None of them is fixable in this repository. Recording the traces so this can go upstream as-is.

    $ grep -rn "Model-host preconnect\|Usage fetch\|plugin MCP connect\|model discovery failed" server/ shared/ src/ scripts/
    (no matches)
    

    1. MCP startup timeouts — user configuration, not app

    stylegallery and stylegallery-material come from the user's own ~/.gjc plugin config. The app never loads them at all — it hard-disables MCP for every session (mcp.discoveryMode, mcp.enableProjectConfig), which is why only the CLI process logs these. Nothing for the app to fix; the entry is either stale in the user's config or the runtime's startup timeout is too tight.

    Related: #161 covers telling app users that MCP is withheld, which is the part that was an app defect.

    2. Invalid port on model-host preconnect — SDK

    node_modules/@gajae-code/coding-agent/src/runtime/network-prewarm-service.ts:

    preconnect(baseUrl) {
        if (!enabled || !baseUrl) return;
        const preconnect = (globalThis.fetch as FetchWithPreconnect).preconnect;
        if (typeof preconnect !== "function") return;
        try {
            preconnect(baseUrl);
        } catch (error) {
            logger.debug("Model-host preconnect failed", { baseUrl, error: ... });
        }
    }

    https://api.anthropic.com carries no port component, and fetch.preconnect rejects it as Invalid port. The catch keeps it best-effort, so nothing breaks — but the prewarm optimization silently never runs for the primary provider on every boot. The URL is passed through verbatim; the defect is in the preconnect call path, inside the SDK.

    3. Duplicate usage polling — SDK

    Usage fetch requested / queued / resolved are emitted from @gajae-code/coding-agent/src/sdk/session.ts. Each process runs its own poller on the same schedule:

    01:35:02.289  pid=16093  Usage fetch requested  providers=[anthropic, google-antigravity, kimi-code, openai-codex]
    01:35:02.289  pid=56360  Usage fetch requested  providers=[anthropic, google-antigravity, kimi-code, openai-codex]
    

    Three gjc processes were live, so provider APIs — including OAuth-backed endpoints — get hit N times for identical data. The scheduling and the cache live in the SDK; the app does not call this.

    4. Local model discovery failures — SDK, and correct

    llama.cpp:8080, lm-studio:1234, omlx:8080 are not running. Logging at debug is right. Listed only because it is part of the same boot-log noise floor, not as a defect.

    Disposition

    Same as #158: keeping this open as an upstream tracking issue rather than an app bug. No app PR will follow.

    The one piece of #162 that was actionable in the app — users never being told MCP is withheld — is filed and fixed separately in #161 / PR #165.

  2. devswha commented on Sep 19, 2026

    @devswha
    OwnerAuthor

    Verified 2026-09-19 against the installed 0.16.4 and the latest published 0.17.2 (npm-pack compared), plus this machine's live logs for today. All four are real; three are unchanged in 0.17.2, one already sits at the level the issue called acceptable.

    1. MCP startup timeouts — still warn, every boot, today

    gjc.2026-09-19.log 21:24:06: both mcp:stylegallery and mcp:stylegallery-material warn MCP server connection timed out during startup. Root cause confirmed user-side: ~/.gjc/agent/mcp.json contains exactly these two entries (npx --yes --package stylegallery …). runtime-mcp/manager.ts in 0.17.2 still has the same per-attempt timeout error path — no one-time-warn change. Removing the two entries from the user config silences it locally; the upstream ask (demote repeated startup timeouts) stands.

    2. Invalid port preconnect — root cause is Bun's fetch.preconnect, reproduced directly

    $ bun -e 'fetch.preconnect("https://api.anthropic.com")'
    Uncaught error: Invalid port
    

    Bun 1.4.0 (the app's pinned runtime) rejects a portless https URL from fetch.preconnect. The SDK's runtime/network-prewarm-service.ts wraps the call in try/catch and logs it at debug — the file is byte-identical in 0.17.2, so upstream did not normalize the URL either. Where this actually gets fixed is Bun (port should default to 443); the SDK could defensively normalize, and the app could revisit its pinned Bun once upstream fixes it. Not present in today's logs because the process that hit it wasn't running; the repro is deterministic.

    3. Usage polling — still per-process fan-out, no sharing added in 0.17.2

    Today's logs show one long-lived process polling all 5 providers every ~5 minutes (7 Usage fetch requested between 21:24 and 21:56). The N× multiplier needs concurrent processes (the original capture had 3); today only one was live, so the magnitude is conditional but the design is unchanged: the 0.17.2 ai/auth-storage.ts diff (638 lines, all plan-classification/refresh work) adds no cross-process cache, election or agent.db sharing — the in-flight "shared" map is process-local. The upstream ask stands.

    4. Local model discovery — already at debug

    Today's boot logged all three (llama.cpp :8080, lm-studio :1234, omlx :8080) at debug, not warn: isQuietLocalDiscoveryFailure demotes loopback connection-refused failures, and Bun's error (code: "ConnectionRefused", message "Unable to connect.") is matched by the classifier. The functions are identical in 0.17.2. The issue already called debug "fine"; this item needs no upstream ask beyond the noise it contributes at debug level.

    Also re-observed today: the notify collision

    Extension command 'notify' from <inline-0> conflicts with built-in commands. Skipping. — warn, every boot (21:24:06). extensibility/extensions/runner.ts in 0.17.2 still emits the identical message with no resolution path.

    Net for the upstream report: items 1, 2, 3 and the notify collision are current as of 0.17.2; item 4 is already at debug and can be dropped from the ask.

  3. devswha commented on Sep 19, 2026

    @devswha
    OwnerAuthor

    Filed upstream after verification against dev @ 2026-09-19 (items 1-3 and the notify collision unchanged there; item 4 already at debug): Yeachan-Heo/gajae-code#5719

  4. devswha commented on Sep 25, 2026

    @devswha
    OwnerAuthor

    Verified on the published 0.17.6 against running builds (app worker and CLI), today's runtime log after the 15:04 KST upgrade:

    • MCP startup timeouts: none (0 MCP connect failed).
    • Model-host preconnect failed … Invalid port: 0 after the upgrade. The last one came from pid 41980 at 15:04:11 KST, 20 s before the 0.17.6 binary replaced the old one.
    • notify extension command collision: 0 after the upgrade (same pid 41980 was the last).
    • Usage polling: each process polls on its own cadence; no same-second N-way fan-out across processes in the window.
    • Local model discovery failures stay at debug, as upstream decided.

    Fixed upstream by Yeachan-Heo/gajae-code#5745, shipped in 0.17.4/0.17.6, and picked up here by #176.

  5. devswha commented on Sep 25, 2026

    @devswha
    OwnerAuthor

    Reopening: the usage-polling item in my close note above was wrong. The other three items hold.

    Today's runtime log after the 0.17.6 upgrade (15:05 KST onward) has 99 Claude usage fetch failed records from 29 distinct processes: 89 × HTTP 429, 10 × 403. Every short-lived gjc -p process fetches Anthropic usage at start, and the app worker polls on its own schedule beside them. In several minutes three or four processes fetched within the same minute, for example 20:26 KST (pids 85035, 98855, 99364, 99424). The 429s are the fan-out hitting the usage endpoint's rate limit. #5745's shared usage polling does not cover separate processes, or not -p runs.

    Filing the remainder upstream.

  6. devswha commented on Sep 25, 2026

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions