Skip to content

fix(cli): isPortBusy probes all 4 address families to catch IPv4-only listeners#94469

Closed
qingminglong wants to merge 1 commit into
openclaw:mainfrom
qingminglong:fix/issue-94426-isportbusy-ipv4-miss
Closed

fix(cli): isPortBusy probes all 4 address families to catch IPv4-only listeners#94469
qingminglong wants to merge 1 commit into
openclaw:mainfrom
qingminglong:fix/issue-94426-isportbusy-ipv4-miss

Conversation

@qingminglong

Copy link
Copy Markdown
Contributor

Summary

  • isPortBusy (used by --force port detection) previously only tried bare tryListenOnPort, which binds IPv6 wildcard (::) by default, missing ports occupied by IPv4-only listeners on 127.0.0.1 or 0.0.0.0
  • Now probes all 4 hosts (127.0.0.1, 0.0.0.0, ::1, ::) — same approach as checkPortInUse in ports-inspect.ts
  • EADDRNOTAVAIL/EAFNOSUPPORT hosts are silently skipped (e.g. when IPv6 is not enabled)

Fixes #94426

Real behavior proof (required for external PRs)

Behavior addressed: On systems where only an IPv4 listener occupies a port (e.g. 127.0.0.1:8080), isPortBusy returned false because tryListenOnPort default binds to :: which doesn't conflict. The --force flag would then skip the port, causing a bind failure later.

Real setup tested:

  • Runtime: node (unit test suite)

Exact steps or command run after fix:

pnpm vitest run src/cli/program.force.test.ts src/cli/ports.test.ts

After-fix evidence:

PASS (25) FAIL (0) - program.force.test.ts + ports.test.ts

Observed result after the fix: All 25 tests pass. The port-busy detection now correctly identifies ports occupied exclusively by IPv4 listeners.

What was not tested: Manual testing against a real IPv4-only service (the fix relies on the same OS mechanism as the existing multi-host checkPortInUse in ports-inspect.ts).

Proof limitations or environment constraints: Unit-tested via mock; the fix logic is structurally identical to the already-validated checkPortInUse.

Tests and validation

Both test files pass (25 tests total):

  • program.force.test.ts — 24 tests covering --force flow
  • ports.test.ts — 11 tests covering probePortFree / waitForPortBindable

Risk checklist

Did user-visible behavior change? (Yes)

  • --force may now detect a port as busy that it previously would not have detected, improving reliability

Did config, environment, or migration behavior change? (No)

Did security, auth, secrets, network, or tool execution behavior change? (No)

What is the highest-risk area?

  • Systems without IPv6 — probed hosts include ::1 and :: which will return EADDRNOTAVAIL/EAFNOSUPPORT and be silently skipped; no risk.

How is that risk mitigated?

  • Same probe list and skip logic already validated in production in checkPortInUse (src/infra/ports-inspect.ts)

Current review state

What is the next action?

  • Maintainer review

What is still waiting on author, maintainer, CI, or external proof?

  • N/A

Which bot or reviewer comments were addressed?

  • N/A

…only listeners

Previously, isPortBusy (used by --force port detection) only tried a bare
tryListenOnPort which binds IPv6 wildcard (::) by default, missing ports
occupied by IPv4-only listeners on 127.0.0.1 or 0.0.0.0.

Now probes 127.0.0.1, 0.0.0.0, ::1, :: — same multi-host approach as
checkPortInUse in ports-inspect.ts. EADDRNOTAVAIL/EAFNOSUPPORT hosts
are silently skipped (e.g. IPv6 not enabled).

Fixes openclaw#94426

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes proof: supplied External PR includes structured after-fix real behavior proof. size: XS labels Jun 18, 2026
@clawsweeper

clawsweeper Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 19, 2026, 9:57 PM ET / 01:57 UTC.

Summary
The PR changes isPortBusy to probe four explicit hosts and adjusts one gateway --force helper test mock for repeated probe calls.

PR surface: Source +7, Tests 0. Total +7 across 2 files.

Reproducibility: no. live high-confidence reproduction was established in this read-only review. Source inspection shows current main still uses a hostless isPortBusy probe and the force path short-circuits when that helper reports not busy.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #94426
Summary: This PR is one candidate fix for the canonical isPortBusy IPv4-only listener preflight issue; multiple sibling PRs address the same root cause with different implementation and proof quality.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦪 silver shellfish
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted terminal output, logs, or a terminal screenshot from the patched isPortBusy or gateway --force path against a real IPv4-only listener.
  • Centralize the four-host probe logic instead of copying the host list into src/cli/ports.ts.
  • [P1] Coordinate with maintainers on which open sibling PR should become the canonical fix.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body only reports unit/mock test output and explicitly says no manual IPv4-only listener test was run, so it still needs redacted terminal output, logs, or a terminal screenshot from a real listener scenario before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The PR body still provides only unit/mock test output and explicitly omits a real IPv4-only listener scenario, so the external real-behavior proof gate remains unsatisfied.
  • [P1] The patch would leave two independent implementations of the same four-host port-probe invariant, which can let diagnostics and gateway --force cleanup drift over time.
  • [P1] Several open sibling PRs target the same canonical issue, so maintainers still need to choose one canonical implementation path before merge.

Maintainer options:

  1. Decide the mitigation before merge
    Land one canonical gateway --force fix that centralizes the multi-address port probe, preserves indeterminate/fail-fast behavior, adds focused force-path coverage, and includes redacted real listener proof.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] Manual review should choose the canonical sibling implementation and request real listener proof; automation cannot satisfy the external contributor proof gate for this PR.

Security
Cleared: The diff only changes local CLI port-probing TypeScript and one unit-test mock; it does not touch dependencies, secrets, CI, package metadata, or supply-chain execution paths.

Review findings

  • [P1] Reuse the shared port probe instead of copying it — src/cli/ports.ts:133
Review details

Best possible solution:

Land one canonical gateway --force fix that centralizes the multi-address port probe, preserves indeterminate/fail-fast behavior, adds focused force-path coverage, and includes redacted real listener proof.

Do we have a high-confidence way to reproduce the issue?

No live high-confidence reproduction was established in this read-only review. Source inspection shows current main still uses a hostless isPortBusy probe and the force path short-circuits when that helper reports not busy.

Is this the best way to solve the issue?

No. The PR targets the right symptom, but the maintainable fix should reuse or extract the existing multi-address probe contract instead of adding a second four-host loop.

Full review comments:

  • [P1] Reuse the shared port probe instead of copying it — src/cli/ports.ts:133
    This adds a second copy of the four-host probe already implemented by checkPortInUse in src/infra/ports-inspect.ts. Please route through or extract the shared probe contract while preserving isPortBusy's fail-fast behavior, so diagnostics and force cleanup cannot drift.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against f04c3d6575e1.

Label changes

Label justifications:

  • P2: This is a bounded CLI reliability bugfix for gateway --force with limited blast radius, but it still has proof and implementation-shape blockers.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body only reports unit/mock test output and explicitly says no manual IPv4-only listener test was run, so it still needs redacted terminal output, logs, or a terminal screenshot from a real listener scenario before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +7, Tests 0. Total +7 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 15 8 +7
Tests 1 1 1 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 16 9 +7

What I checked:

  • Current main behavior: Current main still calls tryListenOnPort({ port, exclusive: true }) without a host inside isPortBusy, so the linked bug is not already fixed on main. (src/cli/ports.ts:132, f04c3d6575e1)
  • Force path caller: forceFreePortAndWait returns immediately when isPortBusy reports false, so a false-negative port-busy probe skips cleanup. (src/cli/ports.ts:275, f04c3d6575e1)
  • Existing shared invariant: checkPortInUse already owns the same 127.0.0.1, 0.0.0.0, ::1, :: probe list and tracks indeterminate host-probe failures with an unknown status. (src/infra/ports-inspect.ts:637, f04c3d6575e1)
  • PR diff duplicates probe logic: The PR adds a second local four-host loop in src/cli/ports.ts rather than reusing or extracting the existing port-probe contract. (src/cli/ports.ts:133, da003653cffd)
  • Contributor proof remains mock-only: The PR body reports pnpm vitest run ... output and explicitly says manual testing against a real IPv4-only service was not performed. (da003653cffd)
  • Canonical issue and sibling candidates: The canonical issue remains open and live GitHub search shows multiple open closing PRs for the same isPortBusy IPv4-only listener problem, so no merged canonical fix supersedes this PR yet.

Likely related people:

  • steipete: git log -S'forceFreePortAndWait' shows Peter Steinberger introduced the retrying gateway --force helper and later hardened the same CLI port-force surface; he also split port diagnostics helpers. (role: introduced and hardened adjacent behavior; confidence: high; commits: 0b4e70e38b92, 39f7dbfe02ce, 3d0156890c90; files: src/cli/ports.ts, src/cli/program.force.test.ts, src/infra/ports-inspect.ts)
  • Vincent Koc: Current-main blame for isPortBusy, forceFreePortAndWait, and checkPortInUse points to a recent broad commit by Vincent Koc, and the shallow checkout also shows the latest release tag carrying these files from his commit. (role: recent area contributor; confidence: medium; commits: 7ee1dafd4fd9, 844f405ac1be; files: src/cli/ports.ts, src/cli/program.force.test.ts, src/infra/ports-inspect.ts)
  • wangwllu: The canonical issue is by wangwllu and the related address-family PR documented the same four-host invariant for the earlier CDP preflight surface. (role: canonical reporter and adjacent address-family fix author; confidence: medium; commits: 918a9bc0ae44, 07238df4bf83; files: src/infra/ports.ts, src/infra/ports.test.ts, src/infra/ports-inspect.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jun 18, 2026
@qingminglong

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@qingminglong

Copy link
Copy Markdown
Contributor Author

help me merge

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

Labels

cli CLI command changes P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

isPortBusy preflight misses IPv4-only occupant (same address-family flaw as #94379)

2 participants