{"id":"0ba51709a6ce8617","repo":"evanw/esbuild","slug":"invalid-serve-path-s","errorCode":null,"errorMessage":"Invalid serve path: %s","messagePattern":"Invalid serve path: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/api/serve_other.go","lineNumber":754,"sourceCode":"\t\treturn ServeResult{}, errors.New(\"Cannot serve a disposed context\")\n\t}\n\n\t// Don't allow starting serve mode multiple times\n\tif ctx.handler != nil {\n\t\treturn ServeResult{}, errors.New(\"Serve mode has already been enabled\")\n\t}\n\n\t// Don't allow starting serve mode multiple times\n\tif (serveOptions.Keyfile != \"\") != (serveOptions.Certfile != \"\") {\n\t\treturn ServeResult{}, errors.New(\"Must specify both key and certificate for HTTPS\")\n\t}\n\n\t// Validate the \"servedir\" path\n\tif serveOptions.Servedir != \"\" {\n\t\tif absPath, ok := ctx.realFS.Abs(serveOptions.Servedir); ok {\n\t\t\tserveOptions.Servedir = absPath\n\t\t} else {\n\t\t\treturn ServeResult{}, fmt.Errorf(\"Invalid serve path: %s\", serveOptions.Servedir)\n\t\t}\n\t}\n\n\t// Validate the \"fallback\" path\n\tif serveOptions.Fallback != \"\" {\n\t\tif absPath, ok := ctx.realFS.Abs(serveOptions.Fallback); ok {\n\t\t\tserveOptions.Fallback = absPath\n\t\t} else {\n\t\t\treturn ServeResult{}, fmt.Errorf(\"Invalid fallback path: %s\", serveOptions.Fallback)\n\t\t}\n\t}\n\n\t// Validate the CORS origins\n\tfor _, origin := range serveOptions.CORS.Origin {\n\t\tif star := strings.IndexByte(origin, '*'); star >= 0 && strings.ContainsRune(origin[star+1:], '*') {\n\t\t\treturn ServeResult{}, fmt.Errorf(\"Invalid origin: %s\", origin)\n\t\t}\n\t}","sourceCodeStart":736,"sourceCodeEnd":772,"githubUrl":"https://github.com/evanw/esbuild/blob/6ff1d8b0d8c134e867a397eef39702a223ebef9e/pkg/api/serve_other.go#L736-L772","documentation":"Returned by internalContext.Serve when serveOptions.Servedir is non-empty but ctx.realFS.Abs(Servedir) fails to produce an absolute path. esbuild needs an absolute, canonical servedir to map incoming request URLs to files; if the filesystem layer cannot absolutize the path (it doesn't exist or can't be resolved), Serve rejects it. The Abs failure returns ok=false.","triggerScenarios":"Calling ctx.Serve({ Servedir: './public' }) where './public' does not exist or cannot be resolved to an absolute path by esbuild's realFS.Abs. The ok check at serve_other.go:751 fails, yielding the error.","commonSituations":"The servedir directory doesn't exist yet (typo, not created); running esbuild from the wrong cwd so the relative path misses; a deployment where the static dir is at a different path than locally; permission issues preventing path resolution.","solutions":["Create the servedir directory before calling Serve().","Verify the path: pass an absolute path or ensure the relative path resolves from esbuild's cwd."],"exampleFix":"// before\nctx.Serve({ Servedir: './public' }); // ./public doesn't exist -> Invalid serve path\n\n// after\nconst fs = require('fs');\nfs.mkdirSync('./public', { recursive: true });\nctx.Serve({ Servedir: path.resolve('./public') });","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst abs = path.resolve(serveOpts.Servedir);\nif (!fs.existsSync(abs) || !fs.statSync(abs).isDirectory()) throw new Error('servedir missing');\nserveOpts.Servedir = abs;","typeGuard":"function isServePathError(e) { return /Invalid serve path/.test(e?.message || ''); }","tryCatchPattern":"try { await ctx.Serve({ Servedir }); } catch (e) { if (isServePathError(e)) { fs.mkdirSync(Servedir, { recursive: true }); /* retry */ } throw e; }","preventionTips":["Create the servedir before calling Serve().","Use absolute paths to avoid cwd ambiguity.","Verify the directory exists and is readable.","Run from the project root or set absWorkingDir."],"tags":["esbuild","serve","configuration","filesystem","validation"],"analyzedSha":"6ff1d8b0d8c134e867a397eef39702a223ebef9e","analyzedAt":"2026-08-03T19:42:38.433Z","schemaVersion":2}