{"record":{"id":"05a3c8742e18f361","repo":"quasarframework/quasar","slug":"project-directory-must-be-a-non-empty-path","errorCode":null,"errorMessage":"Project directory must be a non-empty path","messagePattern":"Project directory must be a non-empty path","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app-vite/lib/utils/remove-build-artifacts.js","lineNumber":62,"sourceCode":"\n  return resolve(realAncestor, relative(existingAncestor, target))\n}\n\nfunction isFilesystemRoot(target) {\n  return target === parse(target).root\n}\n\nexport function getBuildArtifactsCleanTarget({\n  targetDir,\n  projectDir,\n  allowOutsideProject\n}) {\n  if (typeof targetDir !== 'string' || targetDir.trim() === '') {\n    throw new Error('Build output directory must be a non-empty path')\n  }\n\n  if (typeof projectDir !== 'string' || projectDir.trim() === '') {\n    throw new Error('Project directory must be a non-empty path')\n  }\n\n  const project = resolve(projectDir)\n  const effectiveProject = fse.realpathSync(project)\n  const home = fse.realpathSync(resolve(homedir()))\n  const target = resolve(projectDir, targetDir)\n  const effectiveTarget = getEffectivePath(target)\n\n  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","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/quasarframework/quasar/blob/4841521b5f635a971eb9e2710e5542efd194691b/app-vite/lib/utils/remove-build-artifacts.js#L44-L80","documentation":"getBuildArtifactsCleanTarget requires a non-empty projectDir string to anchor path resolution and containment checks. It throws 'Project directory must be a non-empty path' when projectDir is missing, not a string, or blank, since safety checks (home/project containment) cannot be computed without it.","triggerScenarios":"Invoking the clean-artifacts API without projectDir, or with '' / whitespace / a non-string — e.g. when process.cwd() resolution failed or the option was never forwarded from the build pipeline.","commonSituations":"Running the cleaner outside a normal build context (scripts, CI) where cwd assumptions break; a refactor renamed the option; empty environment (deleted cwd directory, so cwd resolution yields '').","solutions":["Pass an explicit absolute projectDir (e.g. path.resolve(__dirname)) instead of relying on cwd","Restore or cd into an existing working directory before running the command","Verify the option key (projectDir) is forwarded correctly through your wrapper/script"],"exampleFix":"// before\nawait removeBuildArtifacts({ targetDir: 'dist', projectDir: '' })\n// after\nawait removeBuildArtifacts({ targetDir: 'dist', projectDir: '/home/me/my-app' })","handlingStrategy":"validation","validationCode":"const path = require('node:path')\nfunction assertNonEmptyString(v, name) {\n  if (typeof v !== 'string' || v.trim() === '') throw new TypeError(`${name} must be a non-empty string`)\n}\nassertNonEmptyString(opts.projectDir, 'projectDir')\n// better: pass an explicit absolute path\nconst projectDir = path.resolve(opts.projectDir || process.cwd())","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim() !== ''\n}","tryCatchPattern":"try {\n  await removeBuildArtifacts(opts)\n} catch (err) {\n  if (err.message === 'Project directory must be a non-empty path') {\n    // fall back to process.cwd() or abort with a clear message\n  } else throw err\n}","preventionTips":["Pass explicit absolute projectDir values; never rely on cwd in scripts/CI","Forward option names exactly (projectDir) through wrappers","Guard against deleted working directories in long-lived processes"],"tags":["validation","config","path"],"backgroundTag":"invalid-path-option","analyzedSha":"4841521b5f635a971eb9e2710e5542efd194691b","analyzedAt":"2026-08-30T01:13:14.944Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}