eyaltoledano/claude-task-master · error · Error
Failed to create directory ${dirPath}: ${error.message}
Error message
Failed to create directory ${dirPath}: ${error.message} What it means
ensureDir() wraps fs.mkdir(dirPath, { recursive: true }) failures into 'Failed to create directory <path>: <reason>'. Recursive mkdir rarely fails on missing parents, so this almost always means an OS-level obstruction: a non-directory exists at the path (or an ancestor), or permission is denied.
Source
Thrown at packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:232
async getStats(filePath: string) {
return fs.stat(filePath);
}
/**
* Read directory contents
*/
async readDir(dirPath: string): Promise<string[]> {
return fs.readdir(dirPath);
}
/**
* Create directory recursively
*/
async ensureDir(dirPath: string): Promise<void> {
try {
await fs.mkdir(dirPath, { recursive: true });
} catch (error: any) {
throw new Error(
`Failed to create directory ${dirPath}: ${error.message}`
);
}
}
/**
* Delete file
*/
async deleteFile(filePath: string): Promise<void> {
try {
await fs.unlink(filePath);
} catch (error: any) {
if (error.code !== 'ENOENT') {
throw new Error(`Failed to delete file ${filePath}: ${error.message}`);
}
}
}
View on GitHub (pinned to c0c98d367c)
Solutions
- Check the OS error in the message: if EEXIST/ENOTDIR, remove or rename the file occupying the path; if EACCES, fix parent-directory permissions.
- Verify the storage root configuration (project path / HOME) points to a writable location.
- If the filesystem is read-only (Docker/CI), mount a writable volume for the .taskmaster directory.
- Free disk space if the error indicates ENOSPC.
Example fix
// before ls -la ~/ | grep .taskmaster # -rw-r--r-- .taskmaster (a file) // after rm ~/ .taskmaster 2>/dev/null; rm ~/.taskmaster && mkdir ~/.taskmaster
Defensive patterns
Strategy: validation
Validate before calling
import { stat } from 'fs/promises';
import path from 'path';
export async function canCreateDir(dirPath: string): Promise<boolean> {
try {
const s = await stat(dirPath);
return s.isDirectory(); // exists and IS a directory
} catch (err: any) {
if (err.code === 'ENOENT') {
const parent = path.dirname(dirPath);
try { await access(parent, constants.W_OK); return true; } catch { return false; }
}
return false;
}
} Try / catch
try {
await fileOps.ensureDir(dirPath);
} catch (err: any) {
if (err.message.startsWith('Failed to create directory')) {
console.error(`Check path ${dirPath}: a file may occupy it or perms deny write (${err.message})`);
throw err;
}
throw err;
} Prevention
- Ensure no file exists at the same path as the intended directory (e.g. a literal file named .taskmaster).
- Use a writable HOME/storage root; mount writable volumes in Docker/CI.
- Run a startup check that the project path's parent is writable.
- Watch for ENOSPC — keep adequate disk headroom.
When it happens
Trigger: ensureDir callers (initialize, saveTasks, logActivity) invoked when the target path or an ancestor exists as a regular file, the filesystem is read-only, or the user lacks write permission on the parent directory.
Common situations: A file named like the directory (e.g. a file literally called '.taskmaster') blocks creation; running in a read-only container image or read-only mount; HOME misconfigured so the storage root resolves to an unwritable path; disk full (ENOSPC).
Related errors
- Failed to read file ${filePath}: ${error.message}
- Failed to read ${filePath} for modification: ${err.message}
- Failed to delete file ${filePath}: ${error.message}
- DIRECTORY_CREATE_FAILED
- CONFIG_ERROR
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/223b67c2390c0b9b.
Report an issue: GitHub.