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

  1. Choose a port in the range 1..65535 (0 means auto-select, defaulting to 8000).
  2. If you need host and port together, use the form --serve=HOST:PORT (e.g. --serve=0.0.0.0:8080).
  3. Validate the port upstream in your shell script with a numeric guard before forwarding it to esbuild --serve=.
  4. 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

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


AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03). Data as JSON: /data/errors/853c47282bd15bb1.json. Report an issue: GitHub.