eyaltoledano/claude-task-master · error · Error
Failed to read file ${filePath}: ${error.message}
Error message
Failed to read file ${filePath}: ${error.message} What it means
readJson() wraps any read failure that is neither ENOENT nor a JSON SyntaxError into 'Failed to read file <path>: <reason>'. This covers filesystem-level problems (permissions, EISDIR, EACCES, I/O errors) encountered while reading the file, as opposed to parse problems.
Source
Thrown at packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts:65
}
return writer;
}
/**
* Read and parse JSON file
*/
async readJson(filePath: string): Promise<any> {
try {
const content = await fs.readFile(filePath, 'utf-8');
return JSON.parse(content);
} catch (error: any) {
if (error.code === 'ENOENT') {
throw error; // Re-throw ENOENT for caller to handle
}
if (error instanceof SyntaxError) {
throw new Error(`Invalid JSON in file ${filePath}: ${error.message}`);
}
throw new Error(`Failed to read file ${filePath}: ${error.message}`);
}
}
/**
* Write JSON file with atomic operation and cross-process locking.
* Uses steno for atomic writes and proper-lockfile for cross-process safety.
* WARNING: This replaces the entire file. For concurrent modifications,
* use modifyJson() instead to prevent lost updates.
*/
async writeJson(
filePath: string,
data: FileStorageData | any
): Promise<void> {
// Ensure file exists for locking (proper-lockfile requires this)
await this.ensureFileExists(filePath);
// Acquire cross-process lock
let release: (() => Promise<void>) | null = null;View on GitHub (pinned to c0c98d367c)
Solutions
- Check the underlying reason in error.message (e.g. EACCES, EISDIR) and fix it — correct the path if it points at a directory.
- Fix permissions: chmod/chown the file or its parent directory so the running user can read it.
- Verify the storage root path configuration points to the intended directory containing the JSON files.
- If running in Docker/CI, mount the .taskmaster directory with correct ownership (match the container user's UID/GID).
Example fix
// before ls -l ~/.taskmaster/tasks.json # -rw------- root root // after sudo chown $(whoami) ~/.taskmaster/tasks.json chmod u+rw ~/.taskmaster/tasks.json
Defensive patterns
Strategy: try-catch
Validate before calling
import { access, constants } from 'fs/promises';
export async function isReadableFile(filePath: string): Promise<boolean> {
try { await access(filePath, constants.R_OK); return true; } catch { return false; }
} Try / catch
try {
const data = await fileOps.readJson(filePath);
} catch (err: any) {
if (err.code === 'ENOENT') return defaultValue;
if (err.message.startsWith('Failed to read file')) {
console.error(`Cannot read ${filePath}: check permissions/path (${err.message})`);
throw err;
}
throw err;
} Prevention
- Ensure the process user owns or can read ~/.taskmaster (chown in Docker entrypoint to match UID).
- Check that configured storage paths point to files, not directories.
- Avoid storing .taskmaster on flaky network mounts; prefer local disk.
- Run a preflight access(R_OK) check when accepting a custom project path.
When it happens
Trigger: Calling readJson (or data/rawData/stateData accessors) when fs.readFile fails for a non-missing-file reason: the path is a directory, the process lacks read permission, the file is on a detached/unmounted volume, or an EBUSY/EIO condition occurs.
Common situations: Running under a different user (CI, Docker) without permissions on ~/.taskmaster; the configured storage path accidentally points at a directory; a Windows file lock held by another process; NFS/disk errors in containerized environments.
Related errors
- Failed to read ${filePath} for modification: ${err.message}
- Failed to create directory ${dirPath}: ${error.message}
- Failed to delete file ${filePath}: ${error.message}
- Failed to copy file from ${srcPath} to ${destPath}: ${error.
- Could not create directory for ${pathType}: ${parentDir}. Er
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/d659d5e83ae72109.
Report an issue: GitHub.