evanw/esbuild · error
Cannot serve without an output path
Error message
Cannot serve %s without an output path
What it means
When using serve mode with entry points, esbuild needs a real output directory to write build artifacts that the server can serve. This error fires when the build is configured to write to stdout (WriteToStdout is true) instead of an output directory. The message distinguishes between 'an entry point' (singular) and 'entry points' (plural).
Solutions
- Set an output directory (outdir) in the build options when using serve mode with entry points
- Remove any stdout-redirecting options such as write:false or stdout-format output
- Do not use entry points with serve mode if you only need to serve static files (use servedir alone)
Example fix
// before
esbuild.build({ entryPoints: ['app.ts'], write: false })
esbuild.serve({ servedir: 'public' })
// after
esbuild.build({ entryPoints: ['app.ts'], outdir: 'public/dist' })
esbuild.serve({ servedir: 'public' }) Defensive patterns
Strategy: validation
Validate before calling
function validateServeConfig(buildOptions) {
if (buildOptions.entryPoints?.length > 0) {
if (!buildOptions.outdir) {
throw new Error('outdir is required when using serve mode with entry points')
}
if (buildOptions.write === false) {
throw new Error('write:false is not compatible with serve mode and entry points')
}
}
}
validateServeConfig(buildOptions) Prevention
- Always set outdir when using serve mode with entry points
- Do not use write:false or stdout output options with serve mode
- Validate your build config for stdout-targeting options before starting serve
When it happens
Trigger: Starting serve mode with one or more entry points while the build writes output to stdout (e.g. using --outfile=/dev/stdout, stdout targeting, or write:false without a proper outdir).
Common situations: Combining serve mode with a build config designed for piping output (e.g. esbuild --bundle --serve without --outdir), or reusing a programmatic build config that had stdout output.
Related errors
- Invalid origin
- 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/2a021f9b41b7cd5c.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/api/serve_other.go:800
}
// 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
relPath, ok := ctx.realFS.Rel(serveOptions.Servedir, ctx.args.options.AbsOutputDir)
if !ok {
return ServeResult{}, fmt.Errorf(
"Cannot compute relative path from %q to %q\n", serveOptions.Servedir, ctx.args.options.AbsOutputDir)
}
relPath = strings.ReplaceAll(relPath, "\\", "/") // Fix paths on Windows
if relPath == ".." || strings.HasPrefix(relPath, "../") {
return ServeResult{}, fmt.Errorf(
"Output directory %q must be contained in serve directory %q",
prettyPrintPath(ctx.realFS, ctx.args.options.AbsOutputDir),
prettyPrintPath(ctx.realFS, serveOptions.Servedir),
)
}View on GitHub (pinned to f6058f8364)