{"id":"853c47282bd15bb1","repo":"evanw/esbuild","slug":"invalid-port-number-s","errorCode":null,"errorMessage":"Invalid port number: %s","messagePattern":"Invalid port number: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cli/cli_impl.go","lineNumber":1461,"sourceCode":"\n\t// Specifying the host is optional\n\tvar err error\n\tif strings.ContainsRune(portText, ':') {\n\t\thost, portText, err = net.SplitHostPort(portText)\n\t\tif err != nil {\n\t\t\treturn api.ServeOptions{}, nil, err\n\t\t}\n\t}\n\n\t// Parse the port\n\tvar port int64\n\tif portText != \"\" {\n\t\tport, err = strconv.ParseInt(portText, 10, 32)\n\t\tif err != nil {\n\t\t\treturn api.ServeOptions{}, nil, err\n\t\t}\n\t\tif port < 0 || port > 0xFFFF {\n\t\t\treturn api.ServeOptions{}, nil, fmt.Errorf(\"Invalid port number: %s\", portText)\n\t\t}\n\t\tif port == 0 {\n\t\t\t// 0 is the default value in Go, which we interpret as \"try to\n\t\t\t// pick port 8000\". So Go uses -1 as the sentinel value instead.\n\t\t\tport = -1\n\t\t}\n\t}\n\n\treturn api.ServeOptions{\n\t\tPort:     int(port),\n\t\tHost:     host,\n\t\tServedir: servedir,\n\t\tKeyfile:  keyfile,\n\t\tCertfile: certfile,\n\t\tFallback: fallback,\n\t\tCORS: api.CORSOptions{\n\t\t\tOrigin: corsOrigin,\n\t\t},","sourceCodeStart":1443,"sourceCodeEnd":1479,"githubUrl":"https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/pkg/cli/cli_impl.go#L1443-L1479","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nesbuild --serve=70000\n\n// after\nesbuild --serve=8080","handlingStrategy":"validation","validationCode":"// Validate the serve port before constructing the CLI invocation.\nfunction validPort(p) {\n  const n = Number(p)\n  return Number.isInteger(n) && n >= 0 && n <= 0xFFFF ? n : null\n}\nconst port = validPort(process.env.SERVE_PORT)\nif (port === null) throw new Error(`Invalid port: ${process.env.SERVE_PORT}`)\n// then: esbuild --serve=PORT","typeGuard":"function isValidPort(value: unknown): value is number {\n  return typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 0xFFFF\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["cli","serve","network","port","config"],"analyzedSha":"6ff1d8b0d8c134e867a397eef39702a223ebef9e","analyzedAt":"2026-08-03T19:42:38.433Z","schemaVersion":2}