You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] IPv6 holder health URL falsely reports a healthy listener as wedged #6174
Package version 0.1.213, current master 33104b1f9545caeb0344193009917ceef9969682. This is a source-level regression report for this exact revision.
Problem
holderProbeOrigin concatenates a bind hostname and port without bracketing IPv6 literals. For ::1 it produces http://::1:PORT, which fetch cannot parse. The failed health probe then labels a healthy listener as wedged/dead and advises killing it during duplicate starts or terminal EADDRINUSE handling.
Proposed correction
Bracket raw IPv6 literals when constructing the probe authority, while preserving IPv4, DNS names, already bracketed literals, and existing wildcard-to-loopback behavior.
Regression coverage
The prepared branch includes focused regression coverage in tests/port-owner.test.ts.
Category K (startup / port diagnostics). Suggested triage: p2, scope/other.
Duplicate screening: this thread already has its fix PR — #6182 ("fix: bracket IPv6 addresses in port-holder health probes"), opened by the reporter and referencing Fixes #6174. Per the one-fix-PR-per-thread rule I did not open a parallel PR; I independently reviewed #6182 against the actual diff (not just its description) and verified CI live.
What I verified
Bug is real and reachable at current master (e3220adc): src/port-owner.ts:227 builds `http://${h}:${port}` with no IPv6 bracketing, so --host ::1 (a valid option, src/cli.ts:196) yields the unparseable http://::1:PORT; the EADDRINUSE / duplicate-start health probe then throws → is caught → reads as "no response" and mislabels a healthy listener as wedged/dead.
The fix is correct and minimal (+2/−1): const authority = h.includes(":") && !h.startsWith("[") ? [${h}] : h; — brackets raw IPv6 literals while preserving IPv4, DNS names, already-bracketed literals, and the existing wildcard→loopback mapping. I hand-traced all four cases plus zone-ID ([internal-ip6]%eth0) and empty-host edges; none regress.
It matches an existing pattern: src/server.ts:1276 (boundOrigin) already does exactly this bracketing ("bracket bare IPv6 literals so the file always holds a valid URL") — so this closes an oversight in holderProbeOrigin, not a new approach.
CI green on the pushed head (9af4b7f): 30 checks, 0 failed / 0 pending across ubuntu×node 22/24 and windows×node 22; the skipped e2e lanes are gated suites not triggered by this change (no request-pipeline files touched). Branch protection leaves it blocked pending a human review/merge.
Related instances found during review (surfaced, not folded in): the same raw-host-no-bracket interpolation appears at a few other host→origin builders — src/launcher.ts:389 (proxyOrigin), src/server/admin.ts:323/552/805 (browser-facing web-UI origins), src/startup-failure-page.ts:54, and the startup banner via displayHost (src/server.ts:1290). These are browser/display-facing (symptom: malformed UI/banner URLs under an IPv6 bind) — a different failure domain from the reported server-side false-diagnosis — so I kept #6182 scoped to the reported repro. Happy to fold them into this PR or track separately; your call.
Activity
Afloat16 commentedon Nov 11, 2026
Proposed fix: #6182. The PR includes focused IPv6 regression coverage and preserves the existing IPv4, hostname and wildcard-to-loopback behavior.
ranxianglei commentedon Nov 11, 2026
(ai: vllm-qwen/qwen3.8-27b)
Duplicate screening: this thread already has its fix PR — #6182 ("fix: bracket IPv6 addresses in port-holder health probes"), opened by the reporter and referencing
Fixes #6174. Per the one-fix-PR-per-thread rule I did not open a parallel PR; I independently reviewed #6182 against the actual diff (not just its description) and verified CI live.What I verified
e3220adc):src/port-owner.ts:227builds`http://${h}:${port}`with no IPv6 bracketing, so--host ::1(a valid option,src/cli.ts:196) yields the unparseablehttp://::1:PORT; the EADDRINUSE / duplicate-start health probe then throws → is caught → reads as "no response" and mislabels a healthy listener as wedged/dead.const authority = h.includes(":") && !h.startsWith("[") ?[${h}]: h;— brackets raw IPv6 literals while preserving IPv4, DNS names, already-bracketed literals, and the existing wildcard→loopback mapping. I hand-traced all four cases plus zone-ID ([internal-ip6]%eth0) and empty-host edges; none regress.src/server.ts:1276(boundOrigin) already does exactly this bracketing ("bracket bare IPv6 literals so the file always holds a valid URL") — so this closes an oversight inholderProbeOrigin, not a new approach.::1server integration test asserting both directions (serving vs. not-wedged), consistent with the Test Blind Spot Retrospective: Reinforcing Negative Assertion Discipline, Tightening Fake Upstream Strictness, Thin Inst | 测试盲区复盘:补反向断言纪律、假上游严格化、薄安装冒烟、形态矩阵与生命周期覆盖 #3617 gate discipline.9af4b7f): 30 checks, 0 failed / 0 pending across ubuntu×node 22/24 and windows×node 22; the skipped e2e lanes are gated suites not triggered by this change (no request-pipeline files touched). Branch protection leaves itblockedpending a human review/merge.bug/p2/scope/other(matching the suggested triage).Related instances found during review (surfaced, not folded in): the same raw-host-no-bracket interpolation appears at a few other host→origin builders —
src/launcher.ts:389(proxyOrigin),src/server/admin.ts:323/552/805(browser-facing web-UI origins),src/startup-failure-page.ts:54, and the startup banner viadisplayHost(src/server.ts:1290). These are browser/display-facing (symptom: malformed UI/banner URLs under an IPv6 bind) — a different failure domain from the reported server-side false-diagnosis — so I kept #6182 scoped to the reported repro. Happy to fold them into this PR or track separately; your call.结构化八问(PR #6182 审核结论)
--host ::1)时,端口占用诊断把健康的监听者误判为「卡死/死亡」,并建议 kill 掉它。holderProbeOrigin(src/port-owner.ts:227)拼http://host:port时没给裸 IPv6 字面量加方括号,::1生成 fetch 无法解析的http://::1:port;探测抛错被吞成「无响应」,于是误判。根因在 URL 生产点,不在下游探测层。[开头)包成[addr],保留 IPv4/DNS/已带括号/wildcard→loopback 既有行为;与src/server.ts:1276boundOrigin既有写法一致。server.ts:734早期孪生冲突退出、server.ts:1681post-bind 终态分支)都受益;无 fail-fast 变吞错、无阈值/时序/输出格式漂移。判定:#6182 在其报告范围内正确、完整地修复了根因,测试双向有牙、CI 全绿,可合入(合并由人工执行)。另发现的浏览器/展示侧同类站点建议单独跟进或并入,待你定夺。