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" directoryView on GitHub (pinned to 6ff1d8b0d8)
Solutions
- Use at most one '*' per origin, e.g. 'https://*.example.com'.
- If you need to allow multiple domains, list each origin as a separate array entry.
- Replace multi-wildcard patterns with explicit origins or a single leading '*'.
- 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
- Use at most one '*' per CORS origin.
- List each allowed domain as a separate array entry.
- Validate origins before calling Serve().
- Prefer explicit origins over broad wildcards.
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
- Invalid serve path: %s
- Invalid fallback path: %s
- Output directory %q must be contained in serve directory %q
- Must specify both key and certificate for HTTPS
- Cannot serve %s without an output path
AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03).
Data as JSON: /data/errors/c0f94006fa56ef54.json.
Report an issue: GitHub.