evanw/esbuild · error
Invalid port number: %s
Error message
Invalid port number: %s
What it means
Thrown by esbuild's serve-mode flag parser (parseServeOptionsImpl) when the value passed to --serve= parses as an integer but falls outside the valid TCP port range. Ports are constrained to 0..65535; note 0 is special-cased elsewhere to mean 'auto-pick 8000'. This fires only for the CLI serve subcommand, not the programmatic Serve() API (which accepts any int without this range gate).
Source
Thrown at pkg/cli/cli_impl.go:1461
// Specifying the host is optional
var err error
if strings.ContainsRune(portText, ':') {
host, portText, err = net.SplitHostPort(portText)
if err != nil {
return api.ServeOptions{}, nil, err
}
}
// Parse the port
var port int64
if portText != "" {
port, err = strconv.ParseInt(portText, 10, 32)
if err != nil {
return api.ServeOptions{}, nil, err
}
if port < 0 || port > 0xFFFF {
return api.ServeOptions{}, nil, fmt.Errorf("Invalid port number: %s", portText)
}
if port == 0 {
// 0 is the default value in Go, which we interpret as "try to
// pick port 8000". So Go uses -1 as the sentinel value instead.
port = -1
}
}
return api.ServeOptions{
Port: int(port),
Host: host,
Servedir: servedir,
Keyfile: keyfile,
Certfile: certfile,
Fallback: fallback,
CORS: api.CORSOptions{
Origin: corsOrigin,
},View on GitHub (pinned to 6ff1d8b0d8)
Solutions
- Choose a port in the range 1..65535 (0 means auto-select, defaulting to 8000).
- If you need host and port together, use the form --serve=HOST:PORT (e.g. --serve=0.0.0.0:8080).
- Validate the port upstream in your shell script with a numeric guard before forwarding it to esbuild --serve=.
- If you were relying on a large port number from another tool, remap it to a free port under 65535.
Example fix
// before esbuild --serve=70000 // after esbuild --serve=8080
Defensive patterns
Strategy: validation
Validate before calling
// Validate the serve port before constructing the CLI invocation.
function validPort(p) {
const n = Number(p)
return Number.isInteger(n) && n >= 0 && n <= 0xFFFF ? n : null
}
const port = validPort(process.env.SERVE_PORT)
if (port === null) throw new Error(`Invalid port: ${process.env.SERVE_PORT}`)
// then: esbuild --serve=PORT Type guard
function isValidPort(value: unknown): value is number {
return typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 0xFFFF
} Prevention
- Centralise serve-port selection in one validated config helper used by every script.
- Prefer 0 (auto-pick) for local dev to avoid collisions.
- Add a CI check that asserts SERVE_PORT is in range before invoking esbuild --serve.
When it happens
Trigger: Run `esbuild --serve=70000` or `esbuild --serve=-1` or `esbuild --serve=99999`. The value must first pass strconv.ParseInt (base 10, 32-bit), then fail the bounds check `port < 0 || port > 0xFFFF`. Non-numeric text like `--serve=abc` produces a different strconv error before reaching this check.
Common situations: Picking a port from an env var or config file that defaults to something out of range; copy-pasting a port from another tool that allows larger numbers; passing a port intended for HTTP/2 ALPN or a dev-server offset that exceeds 65535; using -1 as a 'disabled' sentinel that esbuild does not honor.
Related errors
- Invalid gzip data in archive: ${err && err.message || err}
- Cannot use the "serve" API in this environment
- Failed to download ${JSON.stringify(wasm)}
- Cannot serve a disposed context
- Serve mode has already been enabled
AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03).
Data as JSON: /data/errors/853c47282bd15bb1.json.
Report an issue: GitHub.