{"record":{"id":"a979a1afd6998855","repo":"eyaltoledano/claude-task-master","slug":"failed-to-delete-file-filepath-error-message","errorCode":null,"errorMessage":"Failed to delete file ${filePath}: ${error.message}","messagePattern":"Failed to delete file (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts","lineNumber":246,"sourceCode":"\tasync ensureDir(dirPath: string): Promise<void> {\n\t\ttry {\n\t\t\tawait fs.mkdir(dirPath, { recursive: true });\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to create directory ${dirPath}: ${error.message}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Delete file\n\t */\n\tasync deleteFile(filePath: string): Promise<void> {\n\t\ttry {\n\t\t\tawait fs.unlink(filePath);\n\t\t} catch (error: any) {\n\t\t\tif (error.code !== 'ENOENT') {\n\t\t\t\tthrow new Error(`Failed to delete file ${filePath}: ${error.message}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Rename/move file\n\t */\n\tasync moveFile(oldPath: string, newPath: string): Promise<void> {\n\t\ttry {\n\t\t\tawait fs.rename(oldPath, newPath);\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to move file from ${oldPath} to ${newPath}: ${error.message}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/storage/adapters/file-storage/file-operations.ts#L228-L264","documentation":"deleteFile() calls fs.unlink and swallows ENOENT (deleting a non-existent file is treated as success), but re-throws any other failure as 'Failed to delete file <path>: <reason>'. This is used for tag deletion cleanup of tag-scoped files.","triggerScenarios":"deleteTag (via deleteFile) attempting to unlink a file that exists but cannot be removed: EACCES/EPERM on the file or its directory, EBUSY (file open/locked on Windows), EISDIR (path is a directory), or read-only filesystem (EROFS).","commonSituations":"Running as a user without write permission on the .taskmaster directory; another process (editor, sync client like Dropbox) holding the file open on Windows; the path actually being a directory; deleting from a read-only mounted volume.","solutions":["Check the OS error in the message and fix accordingly: grant write permission on the file's parent directory (deletion requires directory write access).","Close other processes holding the file (editors, sync/backup tools) and retry.","If the path is a directory rather than a file, remove it with the appropriate recursive removal instead.","Note ENOENT is already tolerated — if you get this error the file exists but is unremovable, so no existence check is needed."],"exampleFix":"// before\nrm .taskmaster/tags/feature.json  # rm: permission denied\n// after\nsudo chown -R $(whoami) .taskmaster\nchmod -R u+w .taskmaster","handlingStrategy":"fallback","validationCode":"import { stat, access, constants } from 'fs/promises';\nimport path from 'path';\nexport async function canDeleteFile(filePath: string): Promise<boolean> {\n  try {\n    const s = await stat(filePath);\n    if (!s.isFile()) return false;\n    await access(path.dirname(filePath), constants.W_OK); // dir write permission required to unlink\n    return true;\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await fileOps.deleteFile(filePath);\n} catch (err: any) {\n  if (err.message.startsWith('Failed to delete file')) {\n    // ENOENT is already tolerated by the library; this is EACCES/EBUSY/etc.\n    console.warn(`Could not delete ${filePath} (${err.message}); leaving file in place.`);\n    return; // treat as non-fatal for tag cleanup\n  }\n  throw err;\n}","preventionTips":["Grant write permission on the .taskmaster directory (unlink requires directory write access).","Close editors/sync tools (Dropbox, OneDrive, antivirus) that hold files open on Windows.","Confirm the path is a file, not a directory, before deletion flows.","Treat cleanup deletions as best-effort with warnings rather than hard failures."],"tags":["filesystem","delete","permissions","file-storage"],"backgroundTag":"file-delete-failed","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}