This error occurs when a file or directory name exceeds the maximum length allowed by the operating system's filesystem. Most filesystems limit individual filename components to 255 bytes, and Node.js throws ENAMETOOLONG when attempting filesystem operations with paths that exceed this limit.
The ENAMETOOLONG error (errno 36) is a filesystem-level error that Node.js throws when you attempt to create, open, or manipulate a file or directory whose name component exceeds the maximum length supported by the underlying filesystem. This error specifically refers to individual path components (a single filename or directory name), not the entire path. Most modern filesystems impose a limit of 255 bytes per component, though this can vary by filesystem type and encoding. The error typically manifests during file operations like fs.open(), fs.writeFile(), fs.mkdir(), or any other fs module method that creates or accesses filesystem entries. It's important to note that byte length can differ from character length, especially with multi-byte UTF-8 characters.
Check the error stack trace to identify which file operation is failing:
Error: ENAMETOOLONG: name too long, open '/path/to/very_long_filename...'
at Object.openSync (node:fs:600:3)Extract just the filename component (not the full path) to measure its length:
const path = require('path');
const filename = 'your_problematic_filename_here';
const byteLength = Buffer.byteLength(filename, 'utf8');
console.log(`Filename: ${filename}`);
console.log(`Byte length: ${byteLength}`);
console.log(`Character length: ${filename.length}`);Before performing filesystem operations, validate the filename length:
const fs = require('fs');
const path = require('path');
function validateFilename(filename, maxBytes = 255) {
const byteLength = Buffer.byteLength(filename, 'utf8');
if (byteLength > maxBytes) {
throw new Error(
`Filename exceeds maximum length: ${byteLength} bytes (max: ${maxBytes})`
);
}
return filename;
}
// Use it before file operations
const filename = generateFilename(); // your filename generation logic
validateFilename(filename);
fs.writeFileSync(path.join('/some/dir', filename), data);Truncate long filenames while preserving uniqueness using a hash:
const crypto = require('crypto');
const path = require('path');
function truncateFilename(filename, maxBytes = 255) {
const ext = path.extname(filename);
const basename = path.basename(filename, ext);
const byteLength = Buffer.byteLength(filename, 'utf8');
if (byteLength <= maxBytes) {
return filename;
}
// Reserve space for extension and hash
const hashLength = 8;
const maxBaseLength = maxBytes - Buffer.byteLength(ext, 'utf8') - hashLength - 1;
// Truncate basename and add hash of original
const hash = crypto
.createHash('md5')
.update(basename)
.digest('hex')
.slice(0, hashLength);
let truncated = basename;
while (Buffer.byteLength(truncated, 'utf8') > maxBaseLength) {
truncated = truncated.slice(0, -1);
}
return `${truncated}-${hash}${ext}`;
}
// Example usage
const longFilename = 'very_very_long_filename_that_exceeds_filesystem_limits.json';
const safeFilename = truncateFilename(longFilename);
console.log(safeFilename); // very_very_long_filename_that_exceeds_filesys-a1b2c3d4.jsonRedesign your filename generation to avoid length issues:
// BAD: Concatenating multiple long strings
const filename = `${userId}_${timestamp}_${description}_${category}_${tags.join('_')}.json`;
// GOOD: Use hierarchical directories and shorter names
const dir = path.join('data', userId, category);
const filename = `${timestamp}.json`;
fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(path.join(dir, filename), data);
// GOOD: Use UUIDs or short hashes
const { v4: uuidv4 } = require('uuid');
const filename = `${uuidv4()}.json`;
// GOOD: Store metadata separately from filename
const filename = 'data.json';
const metadata = { userId, description, category, tags };
fs.writeFileSync(path.join(dir, filename), data);
fs.writeFileSync(path.join(dir, 'metadata.json'), JSON.stringify(metadata));If encountering ENAMETOOLONG during npm/pnpm installs:
# For npm: Update to latest version (better at flattening dependencies)
npm install -g npm@latest
# For pnpm: Use shamefully-hoist to flatten node_modules
echo "shamefully-hoist=true" >> .npmrc
pnpm install
# For any package manager: Clean and reinstall
rm -rf node_modules package-lock.json
npm installConsider using pnpm's content-addressable storage which avoids deep nesting:
npm install -g pnpm
pnpm installFilesystem-Specific Limits:
Different filesystems have different limits for filename components:
- ext2/ext3/ext4 (Linux): 255 bytes
- NTFS (Windows): 255 UTF-16 characters (510 bytes)
- APFS (macOS): 255 UTF-8 bytes
- FAT32: 255 characters
- exFAT: 255 UTF-16 characters
Note that byte length differs from character length with multi-byte UTF-8 characters. A filename with 200 emoji characters could exceed 255 bytes.
Full Path vs. Component Limits:
While ENAMETOOLONG specifically refers to individual filename components, be aware of full path limits:
- Linux: PATH_MAX is typically 4096 bytes
- Windows: Traditional MAX_PATH is 260 characters (can be extended in Windows 10+)
- macOS: Approximately 1024 bytes for full paths
Edge Cases in Build Tools:
Some build tools and testing frameworks flatten directory structures into single filenames, which can trigger ENAMETOOLONG:
- TypeScript compilation with deep node_modules paths
- Gatsby page data generation from long slugs
- Vitest debug dumps with long test names
- Webpack cache keys from long module paths
In these cases, configure the tool to use shorter paths or update to versions with better path handling.
Buffer.byteLength vs String.length:
Always use Buffer.byteLength() to check filesystem limits, not String.length:
const filename = '你好世界.txt'; // Chinese characters
console.log(filename.length); // 7 (characters)
console.log(Buffer.byteLength(filename, 'utf8')); // 15 (bytes)Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams