Mateen Kiani
Published on Mon Jul 14 2025·4 min read
Deleting files is a common task when managing server-side resources in Node.js. Whether you’re cleaning up temp directories or removing outdated logs, understanding how to safely delete files is essential. Yet developers often overlook race conditions or error handling, leading to crashes or data loss. How can you ensure a smooth, error-free deletion process in your Node.js apps?
By mastering the fs
module’s deletion methods and combining them with proper checks and error management, you can confidently remove files without surprises. This guide walks you through everything from basic unlink calls to bulk deletion, with practical code examples, tips, and best practices.
The core API for deleting files in Node.js is the fs
module. Two methods stand out:
fs.unlink(path, callback)
– Asynchronous and non-blocking.fs.unlinkSync(path)
– Synchronous and blocking.Asynchronous deletion is preferred in production since it won’t hold up your event loop. Here’s a simple example:
const fs = require('fs');const filePath = './temp.txt';fs.unlink(filePath, (err) => {if (err) {console.error('Failed to delete file:', err);return;}console.log('File deleted successfully');});
If you need a script that runs in sequence, the synchronous version can be useful:
try {fs.unlinkSync(filePath);console.log('File removed');} catch (err) {console.error('Error deleting file:', err);}
Tip: Avoid
fs.unlinkSync
in servers handling live traffic, as it can block other operations.
Attempting to delete a non-existent file throws an error. To handle this gracefully, you can verify the file’s presence first. One approach is to use fs.stat
or the simpler fs.access
:
const fs = require('fs');const path = './old.log';fs.access(path, fs.constants.F_OK, (err) => {if (err) {console.warn('File does not exist, skipping deletion.');} else {fs.unlink(path, (err) => {if (err) console.error('Delete error:', err);else console.log('Deleted', path);});}});
For detailed strategies on file checks and existence patterns, see nodejs-check-if-file-exists.
When working with directories full of files, manual loops can be tedious. Node.js 12+ supports recursive removal with fs.rmdir
(and in 14+
fs.rm
). For older versions or more control, use a helper to list files and delete them:
const fs = require('fs');const path = require('path');function deleteFolderContents(dir) {fs.readdir(dir, (err, files) => {if (err) return console.error(err);files.forEach((file) => {const fullPath = path.join(dir, file);fs.stat(fullPath, (err, stats) => {if (stats.isDirectory()) {deleteFolderContents(fullPath);fs.rmdir(fullPath, (err) => err && console.error(err));} else {fs.unlink(fullPath, (err) => err && console.error(err));}});});});}deleteFolderContents('./logs');
You can also combine this with listing files in a directory for filtering or additional checks.
File deletion can fail due to permissions, locks by other processes, or networked filesystems. Always wrap your calls in try/catch (for sync) or check err.code
in callbacks:
fs.unlink('secret.txt', (err) => {if (err) {switch (err.code) {case 'EACCES':console.error('Permission denied');break;case 'EPERM':console.error('Operation not permitted');break;default:console.error('Unknown error', err);}} else {console.log('File removed');}});
Always log or handle specific error codes to aid debugging and user feedback.
• Use async APIs: Keep your server responsive by using non-blocking calls.
• Validate paths: Sanitize input paths to avoid directory traversal or accidental deletes outside your intended folder.
• Implement backups: For critical data, move files to a “trash” folder before permanent removal.
• Leverage Promises: Modern code often prefers fs.promises.unlink
for cleaner async/await
syntax:
const { unlink } = require('fs').promises;async function safeDelete(path) {try {await unlink(path);console.log('Deleted', path);} catch (err) {console.error('Delete failed:', err);}}
• Clean up on exit: Hook into process signals (SIGINT
, SIGTERM
) to remove temp files when your app shuts down.
Deleting files in Node.js may seem straightforward, but handling it properly prevents data loss, unhandled exceptions, and blocked workflows. By using the fs
module’s async methods, checking file existence, managing bulk and recursive deletes, and handling permissions and errors, you build robust file-management routines. Always follow best practices like path validation, backups, and non-blocking calls to keep your application stable and predictable. Armed with these techniques, you can confidently manage file deletion in any Node.js project.