evanw/esbuild · error

Invalid origin: %s

Error message

Invalid origin: %s

What it means

Returned by internalContext.Serve when a CORS origin in serveOptions.CORS.Origin contains more than one '*' wildcard. esbuild allows a single '*' per origin pattern (for subdomain matching like 'https://*.example.com') but rejects multiple wildcards because they are ambiguous and not meaningfully matchable. The check scans for the first '*' and errors if another '*' appears after it.

Source

Thrown at pkg/api/serve_other.go:770

			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 6ff1d8b0d8)

Solutions

  1. Use at most one '*' per origin, e.g. 'https://*.example.com'.
  2. If you need to allow multiple domains, list each origin as a separate array entry.
  3. Replace multi-wildcard patterns with explicit origins or a single leading '*'.
  4. Validate each CORS origin has zero or one '*' before calling Serve().

Example fix

// before
ctx.Serve({ CORS: { Origin: ['https://*.example.*'] } }); // two wildcards

// after
ctx.Serve({ CORS: { Origin: ['https://*.example.com', 'https://example.*'] } });
Defensive patterns

Strategy: validation

Validate before calling

function validOrigins(origins) {
  return origins.every(o => (o.match(/\*/g) || []).length <= 1);
}
if (!validOrigins(serveOpts.CORS.Origin)) throw new Error('CORS origin has multiple wildcards');

Type guard

function isValidOrigin(o) { return typeof o === 'string' && (o.match(/\*/g) || []).length <= 1; }

Try / catch

try { await ctx.Serve({ CORS: { Origin } }); } catch (e) { if (/Invalid origin/.test(e.message)) { Origin = Origin.map(fixMultiWildcard); /* retry */ } throw e; }

Prevention

When it happens

Trigger: Calling ctx.Serve() with CORS.Origin containing an entry like 'https://*.*.com' or 'https://*.example.*'. The check at serve_other.go:769 finds a second '*' after the first and returns the error.

Common situations: Trying to allow multiple subdomain levels with '*.example.*'; copy-pasting an overly broad CORS pattern; misunderstanding CORS wildcard semantics; a config that joins several patterns with '*' separators.

Related errors


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