CherryHQ/cherry-studio · error · Error
Failed to delete: ${error.message}
Error message
Failed to delete: ${error.message} What it means
The catch-all for deletion failures that are neither ENOENT (handled at line 45) nor ENOTEMPTY (handled at line 68). It wraps any remaining NodeFileSystemError into 'Failed to delete: <message>'. Common underlying codes include EACCES/EPERM (permission), EBUSY (file in use on Windows), EROFS (read-only filesystem), or EMFILE (too many open files). The original error code is dropped — only message survives.
Source
Thrown at src/main/ai/mcp/servers/filesystem/tools/delete.ts:71
// Perform deletion
try {
if (isDirectory) {
if (recursive) {
// Delete directory recursively
await fs.rm(validPath, { recursive: true, force: true })
} else {
// Try to delete empty directory
await fs.rmdir(validPath)
}
} else {
// Delete file
await fs.unlink(validPath)
}
} catch (error: any) {
if (error.code === 'ENOTEMPTY') {
throw new Error(`Directory not empty: ${targetPath}. Use recursive=true to delete non-empty directories.`)
}
throw new Error(`Failed to delete: ${error.message}`)
}
// Log the operation
logger.info('Path deleted', {
path: validPath,
type: isDirectory ? 'directory' : 'file',
recursive: isDirectory ? recursive : undefined
})
// Format output
const itemType = isDirectory ? 'Directory' : 'File'
const recursiveNote = isDirectory && recursive ? ' (recursive)' : ''
return {
content: [
{
type: 'text',
text: `${itemType} deleted${recursiveNote}: ${relativePath}`View on GitHub (pinned to 726446b54c)
Solutions
- Check filesystem permissions on the target and its parent directory (write+execute on parent needed for deletion).
- On Windows, ensure no process (including the Electron app itself) holds the file open.
- Preserve the error code in the message so EACCES vs EBUSY vs EROFS is diagnosable — the current message loses that detail.
- If the underlying cause is EMFILE, raise the file descriptor limit or reduce concurrent file operations.
Example fix
// before
throw new Error(`Failed to delete: ${error.message}`)
// after — keep the errno code for diagnosis
throw new Error(`Failed to delete (${error.code ?? 'UNKNOWN'}): ${error.message}`) Defensive patterns
Strategy: try-catch
Type guard
// Classify the underlying filesystem error code to choose a remedy.
function isPermissionError(e: unknown): boolean {
return e instanceof Error && /EACCES|EPERM/.test((e as any).code ?? '')
} Try / catch
// Map fs error codes to actionable messages.
try {
isDirectory ? await fs.rm(validPath, { recursive, force: true }) : await fs.unlink(validPath)
} catch (e: any) {
if (e.code === 'ENOTEMPTY') throw new Error(`Directory not empty: ${targetPath}`)
if (/EACCES|EPERM/.test(e.code)) throw new Error(`Permission denied deleting ${targetPath}`)
if (e.code === 'EBUSY') throw new Error(`File in use: ${targetPath}`)
throw new Error(`Failed to delete (${e.code}): ${e.message}`)
} Prevention
- Confirm write+execute permission on the target's parent directory before deleting.
- On Windows, ensure no process (including the Electron app) holds the file open.
- Preserve the underlying errno code in the message for diagnosis.
- Watch the file descriptor count (EMFILE) when deleting many files concurrently.
When it happens
Trigger: The process lacks write/delete permission on the target; on Windows the file is open in another process or held by an antivirus; the target lives on a read-only mount; the file descriptor limit is exhausted.
Common situations: Files created by a different user and not chmod'd; Windows file locking; deleting from a mounted read-only snapshot; sandbox environments that forbid deletion outside an allowlist.
Related errors
- Failed to read journal at ${journalPath}: ${(err as Error).m
- Path not found: ${targetPath}
- Directory not empty: ${targetPath}. Use recursive=true to de
- Failed to create parent directory: ${error.message}
- Failed to write file: ${error.message}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/84869ba81dad35d2.
Report an issue: GitHub.