{"record":{"id":"874fa9e30a4d55fb","repo":"remotion-dev/remotion","slug":"unexpected-build-output-path-output-path","errorCode":null,"errorMessage":"Unexpected build output path: ${output.path}","messagePattern":"Unexpected build output path: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/promo-pages/bundle.ts","lineNumber":94,"sourceCode":"for (const result of results) {\n\tif (!result.success) {\n\t\tconsole.log(result.logs.join('\\n'));\n\t\tprocess.exit(1);\n\t}\n\n\tfor (const output of result.outputs) {\n\t\t// On Windows, Bun may return absolute output paths here. Normalize them back\n\t\t// into the local dist directory so we don't accidentally write invalid paths.\n\t\tconst relativeOutputPath = path.isAbsolute(output.path)\n\t\t\t? path.relative(outdir, output.path)\n\t\t\t: output.path;\n\t\tconst normalizedOutputPath = relativeOutputPath.replaceAll('\\\\', '/');\n\t\tconst outputPathWithoutDistPrefix = normalizedOutputPath.startsWith('dist/')\n\t\t\t? normalizedOutputPath.slice('dist/'.length)\n\t\t\t: normalizedOutputPath;\n\n\t\tif (outputPathWithoutDistPrefix.startsWith('../')) {\n\t\t\tthrow new Error(`Unexpected build output path: ${output.path}`);\n\t\t}\n\n\t\tawait Bun.write(\n\t\t\tpath.join('dist', outputPathWithoutDistPrefix),\n\t\t\tawait output.text(),\n\t\t);\n\t}\n}\n\nexport {};\n","sourceCodeStart":76,"sourceCodeEnd":105,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/promo-pages/bundle.ts#L76-L105","documentation":"The promo-pages bundle script copies every esbuild build output into the dist/ directory, but first normalizes the output path and rejects any file that resolves outside dist/. If a relative output path still starts with '../' after stripping the 'dist/' prefix, the build fails fast rather than writing files outside the intended output directory.","triggerScenarios":"Running the bundle script (bun packages/promo-pages/bundle.ts or its build pipeline) when esbuild emits an output file whose resolved path escapes dist/, e.g. a chunk or asset with an outbase/outdir misconfiguration producing paths like '../shared/foo.js'.","commonSituations":"Misconfigured esbuild `outbase` after moving entry points; adding a new entry point in a parent directory; changing `outdir` so emitted chunk paths contain '..'; symlinked or nested entry files changing relative path computation.","solutions":["Check the esbuild config in bundle.ts: set `outbase` (usually the source root) so all outputs land under dist/ without '../' segments.","Move entry points so they all live below the directory used as outbase.","Log output.path (console.log(output.path)) right before the throw to see which file escapes and fix its entry/asset config.","If the file genuinely must live outside dist/, copy it explicitly after the build instead of routing it through esbuild outputs."],"exampleFix":"// before\nawait esbuild.build({ entryPoints: ['./src/index.ts', '../shared/entry.ts'], outdir: 'dist' });\n// after\nawait esbuild.build({ entryPoints: ['./src/index.ts', './src/shared-entry.ts'], outdir: 'dist', outbase: 'src' });","handlingStrategy":"validation","validationCode":"// pre-validate the esbuild config mapping\nconst outbase = 'src';\nfor (const entry of entryPoints) {\n  const rel = path.relative(outbase, entry);\n  if (rel.startsWith('..')) throw new Error(`Entry outside outbase: ${entry}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await build();\n} catch (e) {\n  if (String(e.message).startsWith('Unexpected build output path')) {\n    console.error('Fix esbuild outbase/outdir so outputs stay under dist/', e.message);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Always set an explicit outbase covering all entry points.","Add a CI check that no esbuild output path contains '..'.","Keep entry points within a single source root directory."],"tags":["build","esbuild","path-resolution","config"],"backgroundTag":"path-traversal-blocked","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}