tauri-apps/tauri · error · Error

' ' is not a directory.

Error message

'${path}' is not a directory.

What it means

Rollup's cleanDir helper opens a directory with opendirSync before unlinking its contents. ENOENT is treated as a no-op (nothing to clean), but ENOTDIR means the given path exists and is a file (or other non-directory), so cleaning would be meaningless and the build aborts with this error.

Solutions

  1. Remove or rename the file currently occupying the path that should be a directory
  2. Verify the output path passed to cleanDir is the intended directory and does not point at a file
  3. Re-run the build; if a tool keeps recreating a file there, fix that tool's output config

Example fix

// before
rm -f dist
// after
rm -rf dist  # ensure the path is a directory (or absent), not a plain file
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from 'node:fs';
function assertIsDirectoryOrAbsent(p: string) {
  try { if (!statSync(p).isDirectory()) throw new Error(`${p} is not a directory`); }
  catch (e: any) { if (e.code !== 'ENOENT') throw e; }
}

Type guard

function isDirectory(p: string): boolean {
  try { return statSync(p).isDirectory(); } catch { return false; }
}

Try / catch

try { cleanDir(outputPath); } catch (err: any) {
  if (err.message.includes('is not a directory')) {
    rmSync(outputPath); cleanDir(outputPath); // remove offending file and retry
  } else throw err;
}

Prevention

When it happens

Trigger: The cleanDir() function in packages/api/rollup.config.ts is called with a path that resolves to an existing regular file or symlink-to-file instead of a directory (e.g. a stale artifact, or outputDir pointing at a file).

Common situations: A previous build wrote a file where a directory was expected; someone replaced the dist/output directory with a file; a misconfigured output path in rollup.config.ts; a symlink pointing to a file rather than a directory.

Related errors


AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18). Data as JSON: /api/errors/5fba48b714c29d05. Report an issue: GitHub.

Appendix: source

Thrown at packages/api/rollup.config.ts:104

    writeBundle() {
      // copy necessary files like `CHANGELOG.md` , `README.md` and Licenses to `./dist`
      fg.sync('(LICENSE*|*.md|package.json)').forEach((f) =>
        copyFileSync(f, `dist/${f}`)
      )
    }
  }
}

function cleanDir(path: string) {
  let dir: Dir
  try {
    dir = opendirSync(path)
  } catch (err: any) {
    switch (err.code) {
      case 'ENOENT':
        return // Noop when directory don't exists.
      case 'ENOTDIR':
        throw new Error(`'${path}' is not a directory.`)
      default:
        throw err
    }
  }

  let file = dir.readSync()
  while (file) {
    const filePath = join(path, file.name)
    rmSync(filePath, { recursive: true })
    file = dir.readSync()
  }
  dir.closeSync()
}

View on GitHub (pinned to 460ec35447)