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
- Use only one '*' wildcard per origin string
- List multiple separate origins if you need to match different patterns
- 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
- Use at most one '*' wildcard per CORS origin string
- List multiple separate origin patterns instead of using multiple wildcards in one
- Validate CORS origins against this rule before starting serve
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
- Cannot serve without an output path
- Invalid port number
- Must specify both key and certificate for HTTPS
- Output directory must be contained in serve directory
- Cannot compute relative path from
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" directoryView on GitHub (pinned to f6058f8364)