evanw/esbuild · error

Invalid origin

Error message

Invalid origin: %s

What it means

Each CORS origin string in serve mode may contain at most one asterisk wildcard. This error fires when an origin contains two or more '*' characters, detected by finding a '*' and then another '*' in the remainder of the string. Multiple wildcards are not supported because they create ambiguous match patterns.

Solutions

  1. Use only one '*' wildcard per origin string
  2. List multiple separate origins if you need to match different patterns
  3. Use a single wildcard at the broadest level, e.g. 'https://*.example.com'

Example fix

// before
esbuild.serve({ cors: { origin: ['https://*.*.example.com'] } })
// after
esbuild.serve({ cors: { origin: ['https://*.example.com', 'https://*.api.example.com'] } })
Defensive patterns

Strategy: validation

Validate before calling

function validateCorsOrigins(origins) {
  for (const origin of origins) {
    const firstStar = origin.indexOf('*')
    if (firstStar >= 0 && origin.indexOf('*', firstStar + 1) >= 0) {
      throw new Error(`CORS origin has multiple wildcards: ${origin}`)
    }
  }
}
validateCorsOrigins(serveOptions.cors.origin || [])

Prevention

When it happens

Trigger: Passing --cors-origin=https://*.*.example.com or the JS API equivalent with multiple asterisks in a single origin string.

Common situations: Misunderstanding CORS wildcard syntax and trying to match multiple subdomain levels with multiple wildcards (e.g. https://*.api.*.com).

Related errors


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

Appendix: source

Thrown at pkg/api/serve_other.go:787

			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)
		}
	}

	// Validate the CORS origins
	for _, origin := range serveOptions.CORS.Origin {
		if star := strings.IndexByte(origin, '*'); star >= 0 && strings.ContainsRune(origin[star+1:], '*') {
			return ServeResult{}, fmt.Errorf("Invalid origin: %s", origin)
		}
	}

	// Stuff related to the output directory only matters if there are entry points
	outdirPathPrefix := ""
	if len(ctx.args.entryPoints) > 0 {
		// Don't allow serving when builds are written to stdout
		if ctx.args.options.WriteToStdout {
			what := "entry points"
			if len(ctx.args.entryPoints) == 1 {
				what = "an entry point"
			}
			return ServeResult{}, fmt.Errorf("Cannot serve %s without an output path", what)
		}

		// Compute the output path prefix
		if serveOptions.Servedir != "" && ctx.args.options.AbsOutputDir != "" {
			// Make sure the output directory is contained in the "servedir" directory

View on GitHub (pinned to f6058f8364)