{"record":{"id":"b9ffef9588b63416","repo":"quasarframework/quasar","slug":"build-output-directory-must-remain-inside-the-proj","errorCode":null,"errorMessage":"Build output directory must remain inside the project. Set build.allowOutsideProjectDistDir to true to explicitly allow an external directory.","messagePattern":"Build output directory must remain inside the project\\. Set build\\.allowOutsideProjectDistDir to true to explicitly allow an external directory\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app-vite/lib/utils/remove-build-artifacts.js","lineNumber":89,"sourceCode":"  if (isFilesystemRoot(target) || isFilesystemRoot(effectiveTarget)) {\n    throw new Error('Refusing to remove a filesystem root as build output')\n  }\n\n  if (target === home || effectiveTarget === home) {\n    throw new Error(\n      'Refusing to remove the user home directory as build output'\n    )\n  }\n\n  if (target === project || effectiveTarget === effectiveProject) {\n    throw new Error('Refusing to remove the project root as build output')\n  }\n\n  if (\n    allowOutsideProject !== true &&\n    isContainedPath(effectiveProject, effectiveTarget) === false\n  ) {\n    throw new Error(\n      'Build output directory must remain inside the project. Set build.allowOutsideProjectDistDir to true to explicitly allow an external directory.'\n    )\n  }\n\n  return { target, effectiveTarget }\n}\n\nexport function removeBuildArtifacts(options) {\n  const { target, effectiveTarget } = getBuildArtifactsCleanTarget(options)\n\n  if (fse.pathExistsSync(target) === false) return\n\n  const symlinkTarget =\n    target !== effectiveTarget ? ` (resolves to: ${effectiveTarget})` : ''\n\n  log(`Removing build artifacts: ${target}${symlinkTarget}`)\n\n  if (fse.lstatSync(target).isSymbolicLink()) {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/quasarframework/quasar/blob/4841521b5f635a971eb9e2710e5542efd194691b/app-vite/lib/utils/remove-build-artifacts.js#L71-L107","documentation":"By default the build-artifact cleaner only deletes directories contained within the project. When the resolved build output directory (after symlink resolution) lies outside the effective project directory and allowOutsideProject is not exactly true, this error is thrown so an external directory is never deleted implicitly.","triggerScenarios":"distDir configured as an absolute path outside the project (e.g. ../shared-dist or /var/www/app) while the quasar.config.js build option build.allowOutsideProjectDistDir is absent or not strictly true.","commonSituations":"Deploy setups pointing dist at a sibling webroot; monorepo outputs shared across packages; forgetting the exact boolean true (a truthy string 'true' is not accepted).","solutions":["Add build: { allowOutsideProjectDistDir: true } to quasar.config.js if the external directory is intentional","Prefer moving the output inside the project (distDir: 'dist') and copy/symlink it in your deploy step","Ensure the flag is the boolean true, not the string 'true' or 1"],"exampleFix":"// before\nbuild: { distDir: '../www/app' }\n// after\nbuild: { distDir: '../www/app', allowOutsideProjectDistDir: true }","handlingStrategy":"validation","validationCode":"const path = require('node:path')\nconst fs = require('node:fs')\nconst project = fs.realpathSync(path.resolve(projectDir))\nconst target = fs.realpathSync(path.resolve(projectDir, distDir))\nconst inside = target === project || target.startsWith(project + path.sep)\nif (!inside && allowOutsideProjectDistDir !== true) {\n  throw new Error('dist dir is outside the project; set build.allowOutsideProjectDistDir: true')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await removeBuildArtifacts(opts)\n} catch (err) {\n  if (err.message.includes('must remain inside the project')) {\n    // either move dist inside the project or opt in explicitly\n  } else throw err\n}","preventionTips":["Keep distDir inside the project unless you have a deploy-specific reason","Set build.allowOutsideProjectDistDir: true (boolean) deliberately and document why","Remember only exact true unlocks the behavior — 'true' or 1 will still throw"],"tags":["config","safety","path"],"backgroundTag":"path-outside-project","analyzedSha":"4841521b5f635a971eb9e2710e5542efd194691b","analyzedAt":"2026-08-30T01:13:14.944Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}