Skip to content

Fix: give an EACCES bind failure an actionable message in the dev API server - #692

Open
AmaadMartin wants to merge 1 commit into
mainfrom
fix/dev-server-eacces-actionable-message
Open

Fix: give an EACCES bind failure an actionable message in the dev API server#692
AmaadMartin wants to merge 1 commit into
mainfrom
fix/dev-server-eacces-actionable-message

Conversation

@AmaadMartin

Copy link
Copy Markdown
Owner

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

  1. Link to an existing issue (if applicable):

  2. Or, if no issue exists, describe the change:

Problem: The dev API server rejects an EACCES bind with Node's raw text, listen EACCES: permission denied ::1:8000. The CLI prints only error.message, so that line is the whole diagnostic. Two ordinary situations produce it: a port below 1024 without elevated privileges, and a port inside a block that Hyper-V, WSL2 or the Windows NAT service reserved at boot. In the Windows case nothing holds the socket, so netstat reports the port as free and the operator has no lead.

Solution: One module-level function maps the errno to the reported error. The EACCES message names the address, both causes, the netsh command that lists the Windows reserved ranges, and port 0 as the escape hatch. EADDRINUSE moved into the same function with its wording unchanged, which leaves the listener with no branch of its own and makes the mapping testable without a mock. Every other errno returns unchanged, with the same object identity, so cause chains and programmatic callers keep working.

Two notes for the reviewer:

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

npx vitest run --project unit:dev dev/test/server/adk_api_server_test.ts — 55 passed, 4 of them new. Four new cases cover every arm of the switch: EADDRINUSE wording, the EACCES message and its cause, an unrelated errno, and an error with no code. No existing test changed.

Every new test was run against mutated source and observed to fail:

Mutation Test that failed Failure
Delete the case 'EACCES' arm explains both causes of EACCES expected 'listen EACCES: permission denied ::1:…' to contain 'localhost:80'
default: return new Error(err.message) passes an unrelated errno through unchanged expected Error: read ECONNRESET to be Error: read ECONNRESET { code: 'ECON…' } // Object.is equality
default: return new Error(err.message) passes an error with no code through unchanged expected Error: something else went wrong to be Error: something else went wrong // Object.is equality
`Port ${port} is busy` keeps the in-use wording for EADDRINUSE expected 'Port 8000 is busy' to be 'Port 8000 is already in use'
Listener calls reject(err) and skips toListenError existing: should throw an error if the port is already in use expected [Function] to throw error including 'Port 45447 is already in use' but got 'listen EADDRINUSE: address already in…'

The last mutation pins the wiring: the existing EADDRINUSE startup test drives a real bind failure through start().

Coverage of the new function is 100% of lines and branches (--coverage.include=dev/src/server/adk_api_server.ts; the uncovered lines the reporter lists all pre-date this change and start at line 117).

Manual End-to-End (E2E) Tests:

Linux, as a normal user, from the repository root:

  1. npm run build
  2. node dev/dist/esm/cli_entrypoint.js api_server --port 80 dev/samples
[ADK CLI] Error starting API server: Permission denied binding localhost:80. Ports below 1024 need elevated privileges. Windows also reserves blocks of ports; list them with "netsh interface ipv4 show excludedportrange protocol=tcp". Use a different port, or port 0 for any free port.

Exit code 1. Repeating with --port 0 starts the server and prints http://localhost:44133.

Other checks on the pushed commit: npx eslint and npx prettier --check are clean on both files. npx tsc --noEmit reports 281 errors with and without this change, all in core/test; the count is identical, so this branch adds none.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.

The dev API server rejected an EACCES bind with Node's raw text. The CLI
prints only error.message, so the operator saw no cause and no next step.

Map the errno in one module-level function. The EACCES message names the
address, both causes, the netsh command that lists Windows reserved ports,
and the port 0 escape hatch. EADDRINUSE keeps its wording.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant