quasarframework/quasar · error · Error

Project directory must be a non-empty path

Error message

Project directory must be a non-empty path

What it means

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.

Source

Thrown at app-vite/lib/utils/remove-build-artifacts.js:62

  return resolve(realAncestor, relative(existingAncestor, target))
}

function isFilesystemRoot(target) {
  return target === parse(target).root
}

export function getBuildArtifactsCleanTarget({
  targetDir,
  projectDir,
  allowOutsideProject
}) {
  if (typeof targetDir !== 'string' || targetDir.trim() === '') {
    throw new Error('Build output directory must be a non-empty path')
  }

  if (typeof projectDir !== 'string' || projectDir.trim() === '') {
    throw new Error('Project directory must be a non-empty path')
  }

  const project = resolve(projectDir)
  const effectiveProject = fse.realpathSync(project)
  const home = fse.realpathSync(resolve(homedir()))
  const target = resolve(projectDir, targetDir)
  const effectiveTarget = getEffectivePath(target)

  if (isFilesystemRoot(target) || isFilesystemRoot(effectiveTarget)) {
    throw new Error('Refusing to remove a filesystem root as build output')
  }

  if (target === home || effectiveTarget === home) {
    throw new Error(
      'Refusing to remove the user home directory as build output'
    )
  }

View on GitHub (pinned to 4841521b5f)

Solutions

  1. Pass an explicit absolute projectDir (e.g. path.resolve(__dirname)) instead of relying on cwd
  2. Restore or cd into an existing working directory before running the command
  3. Verify the option key (projectDir) is forwarded correctly through your wrapper/script

Example fix

// before
await removeBuildArtifacts({ targetDir: 'dist', projectDir: '' })
// after
await removeBuildArtifacts({ targetDir: 'dist', projectDir: '/home/me/my-app' })
Defensive patterns

Strategy: validation

Validate before calling

const path = require('node:path')
function assertNonEmptyString(v, name) {
  if (typeof v !== 'string' || v.trim() === '') throw new TypeError(`${name} must be a non-empty string`)
}
assertNonEmptyString(opts.projectDir, 'projectDir')
// better: pass an explicit absolute path
const projectDir = path.resolve(opts.projectDir || process.cwd())

Type guard

function isNonEmptyString(v) {
  return typeof v === 'string' && v.trim() !== ''
}

Try / catch

try {
  await removeBuildArtifacts(opts)
} catch (err) {
  if (err.message === 'Project directory must be a non-empty path') {
    // fall back to process.cwd() or abort with a clear message
  } else throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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 '').

Related errors


AI-assisted analysis of quasarframework/quasar@4841521b5f (2026-08-30). Data as JSON: /api/errors/05a3c8742e18f361. Report an issue: GitHub.