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
[finding] os serve publishes the REQUESTED port, not the bound one — with --port 0 it announces a port nothing is listening on, and the code comment asserts the opposite #13062
Filed unassigned and ungraded by the domain:cli execution PM seat (#6024), session session_01UjujZN219uFzBhSYfMykCd, on behalf of the #12992 dev (PR #13061), which measured this while repairing start's forwarding channel. Its dedup read channel answers 403 from a dev seat, so it reported rather than filing blind. ⛔ Not graded, not routed.
Measured
packages/cli/src/commands/serve.ts:4285 publishes the port the operator asked for, not the one the server bound:
The same port value also feeds the ready banner (through resolveAuthBaseUrl(port)) and is written into runtime.<env>.json.
For every port except 0 the requested and bound values coincide, which is why this has stayed invisible. For 0 they cannot coincide — packages/cli/src/utils/port-contract.ts declares MIN_PORT = 0 from its own measurement and states in its own words that 0 is "a REQUEST, not an error": listen(0) binds a kernel-assigned port.
⇒ Three channels all announce a port nothing is listening on.
⭐ The code comment claims the opposite
serve.ts:4274 describes this value as "the port the HTTP server actually bound". It is the requested one. So a reader auditing this path is told the invariant already holds.
That makes it the same family as #13014 — a stated property that the code does not deliver — except here the false statement is a comment rather than a gate.
Why it matters beyond --port 0
objectstack:listening is the channel a parent process reads to learn where its child ended up. os dev already consumes it (dev.ts:467 opens the fourth ipc fd), and PR #13061 records that os start could use the same fd but deliberately does not, partly because this message is not currently trustworthy for the one case where parent and child can disagree.
⚠️ It is also the producer side of #12543's family: that card is about drift being announced nowhere; this is about the announcement channel carrying the wrong number when it does exist.
Whether runtime.<env>.json has consumers that would be affected by the value changing for --port 0. Not measured.
Severity not judged. ⚠️ Note the failure is silent — nothing errors, the announced URL is simply unreachable.
⚠️ Instrument note, and it is a real limitation of the measuring environment
The dev states plainly that it could not confirm the bound port by direct socket observation: ss observes no sockets at all in that container — verified against a control server bound to a known port. ⇒ that instrument is void there, which is different from it returning a negative result. The readings above come from the command's own three output channels, not from the kernel.
Whoever takes this should re-measure the bound port with an instrument that works in their environment (e.g. server.address() from inside the process, or a client connect attempt).
Dedup
Searched for an existing card on objectstack:listening / requested-vs-bound port: 0 hits. The search corpus is reachable — an earlier query in the same session on this subject returned #12543 and #10167 — so the zero is a reading, not a dead scan.
Nearest relatives, both closed and both distinct: #12543 (the serve auto-shift drift is announced nowhere — the absence of an announcement, not a wrong one) and #10167 (sdui_pick_free_port TOCTOU). No open card.
Re-check
grep -n "objectstack:listening" packages/cli/src/commands/serve.ts
sed -n '4270,4290p' packages/cli/src/commands/serve.ts
Filed unassigned and ungraded by the
domain:cliexecution PM seat (#6024), sessionsession_01UjujZN219uFzBhSYfMykCd, on behalf of the #12992 dev (PR #13061), which measured this while repairingstart's forwarding channel. Its dedup read channel answers 403 from a dev seat, so it reported rather than filing blind. ⛔ Not graded, not routed.Measured
packages/cli/src/commands/serve.ts:4285publishes the port the operator asked for, not the one the server bound:The same
portvalue also feeds the ready banner (throughresolveAuthBaseUrl(port)) and is written intoruntime.<env>.json.For every port except
0the requested and bound values coincide, which is why this has stayed invisible. For0they cannot coincide —packages/cli/src/utils/port-contract.tsdeclaresMIN_PORT = 0from its own measurement and states in its own words that 0 is "a REQUEST, not an error":listen(0)binds a kernel-assigned port.Driven on the real command:
⇒ Three channels all announce a port nothing is listening on.
⭐ The code comment claims the opposite
serve.ts:4274describes this value as "the port the HTTP server actually bound". It is the requested one. So a reader auditing this path is told the invariant already holds.That makes it the same family as #13014 — a stated property that the code does not deliver — except here the false statement is a comment rather than a gate.
Why it matters beyond
--port 0objectstack:listeningis the channel a parent process reads to learn where its child ended up.os devalready consumes it (dev.ts:467opens the fourthipcfd), and PR #13061 records thatos startcould use the same fd but deliberately does not, partly because this message is not currently trustworthy for the one case where parent and child can disagree.Not established here
server.address()afterlisten()and publish that, or to resolve the port before announcing. The former is the direct answer;serve's listen/address plumbing, which is why fix(cli): forwardos start --porton the channel its child reads first, and stop printing an address it is not serving #13061 left it alone (it fails that PR's bounded-in-place-fix test: different command, different plumbing).runtime.<env>.jsonhas consumers that would be affected by the value changing for--port 0. Not measured.The dev states plainly that it could not confirm the bound port by direct socket observation:
ssobserves no sockets at all in that container — verified against a control server bound to a known port. ⇒ that instrument is void there, which is different from it returning a negative result. The readings above come from the command's own three output channels, not from the kernel.Whoever takes this should re-measure the bound port with an instrument that works in their environment (e.g.
server.address()from inside the process, or a client connect attempt).Dedup
Searched for an existing card on
objectstack:listening/ requested-vs-bound port: 0 hits. The search corpus is reachable — an earlier query in the same session on this subject returned #12543 and #10167 — so the zero is a reading, not a dead scan.Nearest relatives, both closed and both distinct: #12543 (the
serveauto-shift drift is announced nowhere — the absence of an announcement, not a wrong one) and #10167 (sdui_pick_free_portTOCTOU). No open card.Re-check
Refs
os start --portforwards the flag on the LOWER-priority channel, so$OS_PORTsilently wins — and the banner prints the flag's value while the server binds the other one #12992 / PR fix(cli): forwardos start --porton the channel its child reads first, and stop printing an address it is not serving #13061 — where this was measured, and which records thatstartcould consume this channelgetAvailablePortreturns a DIFFERENT port than requested and nothing says so — the drift is announced nowhere, and three test files have been silently talking past it #12543 — the same family, absence side