{"id":"b7b593a50f58efad","repo":"evanw/esbuild","slug":"output-directory-q-must-be-contained-in-serve-dir","errorCode":null,"errorMessage":"Output directory %q must be contained in serve directory %q","messagePattern":"Output directory %q must be contained in serve directory %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/api/serve_other.go","lineNumber":796,"sourceCode":"\t\tif ctx.args.options.WriteToStdout {\n\t\t\twhat := \"entry points\"\n\t\t\tif len(ctx.args.entryPoints) == 1 {\n\t\t\t\twhat = \"an entry point\"\n\t\t\t}\n\t\t\treturn ServeResult{}, fmt.Errorf(\"Cannot serve %s without an output path\", what)\n\t\t}\n\n\t\t// Compute the output path prefix\n\t\tif serveOptions.Servedir != \"\" && ctx.args.options.AbsOutputDir != \"\" {\n\t\t\t// Make sure the output directory is contained in the \"servedir\" directory\n\t\t\trelPath, ok := ctx.realFS.Rel(serveOptions.Servedir, ctx.args.options.AbsOutputDir)\n\t\t\tif !ok {\n\t\t\t\treturn ServeResult{}, fmt.Errorf(\n\t\t\t\t\t\"Cannot compute relative path from %q to %q\\n\", serveOptions.Servedir, ctx.args.options.AbsOutputDir)\n\t\t\t}\n\t\t\trelPath = strings.ReplaceAll(relPath, \"\\\\\", \"/\") // Fix paths on Windows\n\t\t\tif relPath == \"..\" || strings.HasPrefix(relPath, \"../\") {\n\t\t\t\treturn ServeResult{}, fmt.Errorf(\n\t\t\t\t\t\"Output directory %q must be contained in serve directory %q\",\n\t\t\t\t\tprettyPrintPath(ctx.realFS, ctx.args.options.AbsOutputDir),\n\t\t\t\t\tprettyPrintPath(ctx.realFS, serveOptions.Servedir),\n\t\t\t\t)\n\t\t\t}\n\t\t\tif relPath != \".\" {\n\t\t\t\toutdirPathPrefix = relPath\n\t\t\t}\n\t\t}\n\t}\n\n\t// Determine the host\n\tvar listener net.Listener\n\tnetwork := \"tcp4\"\n\thost := \"0.0.0.0\"\n\thostIsIP := true\n\tif serveOptions.Host != \"\" {\n\t\thost = serveOptions.Host","sourceCodeStart":778,"sourceCodeEnd":814,"githubUrl":"https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/pkg/api/serve_other.go#L778-L814","documentation":"Returned by internalContext.Serve when the computed relative path from servedir to AbsOutputDir starts with '..' (i.e. the output directory is outside the serve directory). For the HTTP server to serve build output, the output dir must be inside (or equal to) the serve dir; otherwise the files would be unreachable via URLs. The check tests relPath == '..' or strings.HasPrefix(relPath, '../').","triggerScenarios":"Serve() with a Servedir and an AbsOutputDir where outdir is a sibling of or above servedir. Rel succeeds but yields a path beginning with '..', so the guard at serve_other.go:795 fires.","commonSituations":"Setting outdir to '../dist' while servedir is './public'; outdir and servedir as siblings; a default outdir that happens to live outside the served static dir; misconfigured monorepo paths.","solutions":["Move outdir to be inside servedir (e.g. servedir='./www', outdir='./www/assets').","Set servedir to a parent that contains outdir.","If outdir must be elsewhere, drop servedir and serve the outdir directly instead.","Verify with a quick path check that outdir is a subdirectory of servedir before Serve()."],"exampleFix":"// before\nctx = await api.Context({ entryPoints: ['src/index.js'], outdir: './dist' });\nctx.Serve({ Servedir: './public' }); // dist is outside public -> error\n\n// after\nctx = await api.Context({ entryPoints: ['src/index.js'], outdir: './public/dist' });\nctx.Serve({ Servedir: './public' });","handlingStrategy":"validation","validationCode":"const path = require('path');\nfunction isContained(child, parent) {\n  const rc = path.resolve(child), rp = path.resolve(parent);\n  return rc === rp || rc.startsWith(rp + path.sep);\n}\nif (!isContained(outdir, servedir)) throw new Error('outdir must be inside servedir');","typeGuard":null,"tryCatchPattern":"try { await ctx.Serve({ Servedir }); } catch (e) { if (/must be contained in serve directory/.test(e.message)) { /* move outdir under servedir */ } throw e; }","preventionTips":["Put outdir inside servedir.","Or set servedir to a common parent of outdir.","Validate containment with path checks before Serve().","Avoid '../' in outdir relative to servedir."],"tags":["esbuild","serve","configuration","outdir","validation"],"analyzedSha":"6ff1d8b0d8c134e867a397eef39702a223ebef9e","analyzedAt":"2026-08-03T19:42:38.433Z","schemaVersion":2}