evanw/esbuild · error

Must specify both key and certificate for HTTPS

Error message

Must specify both key and certificate for HTTPS

What it means

For HTTPS serve mode, esbuild requires both a key file and a certificate file. This error fires when exactly one of Keyfile or Certfile is set (checked via an XOR comparison: (Keyfile != "") != (Certfile != "")). Both must be provided together, or neither for plain HTTP.

Solutions

  1. Provide both keyfile and certfile paths together
  2. If you do not need HTTPS, omit both keyfile and certfile entirely

Example fix

// before
esbuild.serve({ servedir: '.', keyfile: 'key.pem' })
// after
esbuild.serve({ servedir: '.', keyfile: 'key.pem', certfile: 'cert.pem' })
Defensive patterns

Strategy: validation

Validate before calling

function validateServeOptions(opts) {
  const hasKey = !!opts.keyfile
  const hasCert = !!opts.certfile
  if (hasKey !== hasCert) {
    throw new Error('Both keyfile and certfile must be provided for HTTPS, or neither for HTTP')
  }
}
validateServeOptions(serveOptions)

Prevention

When it happens

Trigger: Passing --keyfile without --certfile (or vice versa) on the CLI, or setting keyfile but not certfile in the serve options.

Common situations: Partially configuring TLS by providing the private key but forgetting the certificate chain, or vice versa, when setting up a dev server.

Understand the failure class

Related errors


AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09). Data as JSON: /api/errors/46cc4ba95a4f5de3. Report an issue: GitHub.

Appendix: source

Thrown at pkg/api/serve_other.go:763

}

func (ctx *internalContext) Serve(serveOptions ServeOptions) (ServeResult, error) {
	ctx.mutex.Lock()
	defer ctx.mutex.Unlock()

	// Ignore disposed contexts
	if ctx.didDispose {
		return ServeResult{}, errors.New("Cannot serve a disposed context")
	}

	// Don't allow starting serve mode multiple times
	if ctx.handler != nil {
		return ServeResult{}, errors.New("Serve mode has already been enabled")
	}

	// Don't allow starting serve mode multiple times
	if (serveOptions.Keyfile != "") != (serveOptions.Certfile != "") {
		return ServeResult{}, errors.New("Must specify both key and certificate for HTTPS")
	}

	// Validate the "servedir" path
	if serveOptions.Servedir != "" {
		if absPath, ok := ctx.realFS.Abs(serveOptions.Servedir); ok {
			serveOptions.Servedir = absPath
		} else {
			return ServeResult{}, fmt.Errorf("Invalid serve path: %s", serveOptions.Servedir)
		}
	}

	// Validate the "fallback" path
	if serveOptions.Fallback != "" {
		if absPath, ok := ctx.realFS.Abs(serveOptions.Fallback); ok {
			serveOptions.Fallback = absPath
		} else {
			return ServeResult{}, fmt.Errorf("Invalid fallback path: %s", serveOptions.Fallback)
		}

View on GitHub (pinned to f6058f8364)