Skip to content

bug(runtime): testProxyConnection hangs behind a proxy and bots/proxied-fetch leaks dispatchers — abort-before-close teardown survives the #5900 transport fix #5978

Description

@MNFConde

What happened

PR #5900 (open at the time of writing) fixes the shared transport for #5898. Two other call sites build their own dispatcher via buildProxyDispatcher() and dispose it themselves, so the same abort-before-close hang survives that fix:

  1. packages/runtime/src/network/proxy-test.ts (testProxyConnection, behind the Desktop "Test current configuration" button). On success its finally runs controller.abort() and then await disposeDispatcher(timedOut), which closes the dispatcher — the same ordering fix(runtime): bound proxied fetch transport teardown #5900 reordered inside the transport. At fix(runtime): bound proxied fetch transport teardown #5900's head (dcd2be3), testProxyConnection against a real proxy is still pending after 25s, long past its 8s probe timeout, and in the Desktop app the button spins forever. The call also occupies the main-process serialized settings lane (enqueue in runtime-host-settings-ipc-main.ts), so once it wedges, subsequent settings:get/settings:update calls queue behind it; that lane is process-local, so a restart clears it. On main pre-fix(runtime): bound proxied fetch transport teardown #5900 the blast radius was larger: host-side policy operations hung as well and silently dropped proxy-setting writes. That wider freeze is how the underlying defect originally surfaced.

  2. packages/runtime/src/bots/proxied-fetch.ts. The success path fire-and-forgets void disposeDispatcher(false) — callers are unblocked, but the dispatcher's destroy never settles, so it leaks per request. Its error path awaits the close after aborting (same shape; not yet reproduced).

How to reproduce

Through the product: enable a network proxy, then Settings → Proxy server → "Test current configuration" — the button spins indefinitely. Standalone: bundle proxy-test.ts with its network/ closure (esbuild, undici 8.11.2) and run testProxyConnection against any reachable HTTP proxy — the returned promise never settles.

Environment

Logs, screenshots, or additional context

Measurement: I bundled proxy-test.ts with its network/ closure (esbuild, undici 8.11.2) and raced testProxyConnection against a 25s timer, against a real HTTP proxy. Two consecutive runs both stayed pending past 25s; the same two-request probe through the #5900 transport settles in milliseconds. The hang is deterministic, not intermittent. Observed both on a packaged desktop build from main and on a dev build at dcd2be3, so this is not a regression introduced by #5900 — that PR simply does not reach these call sites.

Suggested direction

Maintainers' call. The #5900 pattern (destroy before abort, bounded grace) looks directly applicable to proxy-test.ts; proxied-fetch.ts needs a separate decision for the leak and the error path. A regression test in packages/runtime/src/network/__tests__/proxy-test.test.ts — perform a successful request through a proxied dispatcher, then assert testProxyConnection settles within a bound — would cover the first call site.

Provenance

Generative tooling contributed substantively to this report (investigation and drafting with an AI coding assistant); all measurements were verified against the repository and a locally built desktop app.

Activity

  1. ggbdpq commented on Oct 8, 2026

    @ggbdpq
    Contributor

    take

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions