parcel-bundler/parcel · error · FSError
ENOTEMPTY
ENOTEMPTY
Error message
ENOTEMPTY: ${path} isn't empty What it means
ENOTEMPTY raised by `ExtendedMemoryFS._rmdir` when `rimraf`/`rmdir` is called (non-recursive) on a directory whose `readdir` returns one or more entries. Mirrors Node's `fs.rmdir` non-empty semantics.
Source
Thrown at packages/dev/repl/src/parcel/ExtendedMemoryFS.js:167
return super.mkdirp(dir);
}
async _rmdir(
filePath: FilePath,
options: {recursive?: boolean, ...} = {},
): Promise<void> {
let {recursive = false} = options;
if (!recursive) {
if (!this.dirs.has(filePath) && !this.files.has(filePath)) {
throw new FSError('ENOENT', filePath, 'is not a directory');
}
if (
this.dirs.has(filePath) &&
(await this.readdir(filePath)).length > 0
) {
throw new FSError('ENOTEMPTY', filePath, "isn't empty");
}
}
return super.rimraf(filePath);
}
// --------------------------------
rmdir(...args: any): any {
return asyncToNode(args, 3, (...p) => this._rmdir(...p));
}
mkdir(...args: any): any {
return asyncToNode(args, 3, (...p) => this._mkdir(...p));
}
readdir(...args: any): any {
return asyncToNode(args, 3, (...p) => super.readdir(...p));
}
unlink(...args: any): any {View on GitHub (pinned to 59484858a1)
Solutions
- Use `{recursive: true}` to remove the dir and its contents together.
- Empty the directory (remove all children) before calling rmdir.
- Restructure so cleanup happens bottom-up.
Example fix
// before
await fs.rmdir('/a'); // still has files
// after
await fs.rimraf('/a', {recursive: true}); Defensive patterns
Strategy: validation
Validate before calling
async function removeDir(fs, p) {
if ((await fs.readdir(p)).length > 0) await fs.rimraf(p, { recursive: true });
else await fs.rmdir(p);
} Try / catch
try { await fs.rmdir(p); }
catch (e) { if (e.code === 'ENOTEMPTY') await fs.rimraf(p, { recursive: true }); else throw e; } Prevention
- Default to `{recursive: true}` when removing trees.
- Ensure children are removed before parent in custom teardown.
- Treat ENOTEMPTY as 'remove recursively'.
When it happens
Trigger: Calling `fs.rmdir('/a')` on a directory that still contains files or subdirectories, without `{recursive: true}`.
Common situations: Teardown runs before all children are removed; nested writes accumulate under the dir; ported cleanup that assumed children were already gone.
Related errors
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/72c1bf8b985454a7.
Report an issue: GitHub.