eyaltoledano/claude-task-master · error · Error

Failed to get storage stats: ${error.message}

Error message

Failed to get storage stats: ${error.message}

What it means

getStats() aggregates task counts, tag statistics, and storage size by reading the tasks.json file. If any underlying file operation (read, parse, or stat) fails with an error other than ENOENT, the method wraps it in this generic error so callers get a uniform failure message for storage-statistics reads.

Source

Thrown at packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts:116

			return {
				totalTasks,
				totalTags: tags.length,
				lastModified: stats.mtime.toISOString(),
				storageSize: 0, // Could calculate actual file sizes if needed
				tagStats
			};
		} catch (error: any) {
			if (error.code === 'ENOENT') {
				return {
					totalTasks: 0,
					totalTags: 0,
					lastModified: new Date().toISOString(),
					storageSize: 0,
					tagStats: []
				};
			}
			throw new Error(`Failed to get storage stats: ${error.message}`);
		}
	}

	/**
	 * Load tasks from the single tasks.json file for a specific tag
	 * Enriches tasks with complexity data from the complexity report
	 */
	async loadTasks(tag?: string, options?: LoadTasksOptions): Promise<Task[]> {
		const filePath = this.pathResolver.getTasksPath();
		const resolvedTag = tag || 'master';

		try {
			const rawData = await this.fileOps.readJson(filePath);
			let tasks = this.formatHandler.extractTasks(rawData, resolvedTag);

			// Apply filters if provided
			if (options) {
				// Filter by status if specified

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Validate/repair .taskmaster/tasks.json (run it through a JSON linter or restore from git)
  2. Check file and directory permissions on .taskmaster/ and fix with chmod/chown
  3. Read the underlying error.message in the thrown error to identify the real cause (ENOENT is already handled and returns empty stats)
  4. Ensure no concurrent process is writing tasks.json while stats are computed

Example fix

// before: hand-edited, trailing comma in tasks.json
{ "master": { "tasks": [ { "id": 1, "title": "x", }, ] } }
// after: valid JSON
{ "master": { "tasks": [ { "id": 1, "title": "x" } ] } }
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify tasks.json exists and parses before calling getStats
import { readFileSync } from 'fs';
function canReadStats(path = '.taskmaster/tasks.json') {
  try { JSON.parse(readFileSync(path, 'utf8')); return true; }
  catch { return false; }
}
if (!canReadStats()) { /* repair file first */ }

Type guard

function isStorageError(e: unknown): e is Error & { message: string } {
  return e instanceof Error && e.message.startsWith('Failed to get storage stats:');
}

Try / catch

try {
  const stats = await storage.getStats();
} catch (e) {
  if (isStorageError(e)) {
    const cause = e.message.replace('Failed to get storage stats: ', '');
    if (cause.includes('ENOENT')) return emptyStats; // file not created yet
    console.error('Storage stats failed, cause:', cause); // parse/permission issue
  } else throw e;
}

Prevention

When it happens

Trigger: Corrupt or malformed JSON in .taskmaster/tasks.json, permission errors on the tasks file or its directory, readJson throwing a non-ENOENT error (e.g. EACCES, EISDIR, JSON parse errors), or a failure in formatHandler.extractTags/extractMetadata while building stats.

Common situations: Tasks file truncated by a crashed editor or concurrent write, .taskmaster directory permissions changed after cloning a repo as another user, tasks.json hand-edited into invalid JSON, or the path resolving to a directory instead of a file.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/d3ccb3824e4a1287. Report an issue: GitHub.