{"record":{"id":"f3a26bd505170a76","repo":"eyaltoledano/claude-task-master","slug":"failed-to-restore-backup-error-message","errorCode":null,"errorMessage":"Failed to restore backup: ${error.message}","messagePattern":"Failed to restore backup: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/tm-core/src/modules/workflow/managers/workflow-state-manager.ts","lineNumber":231,"sourceCode":"\t\t\tif (error.code === 'ENOENT') {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\tthrow new Error(`Failed to list backups: ${error.message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Restore from a backup\n\t */\n\tasync restoreBackup(backupFileName: string): Promise<void> {\n\t\ttry {\n\t\t\tconst backupPath = path.join(this.backupDir, backupFileName);\n\t\t\tconst content = await fs.readFile(backupPath, 'utf-8');\n\t\t\tconst backup: WorkflowStateBackup = JSON.parse(content);\n\n\t\t\tawait this.save(backup.state);\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(`Failed to restore backup: ${error.message}`);\n\t\t}\n\t}\n\n\t/**\n\t * Prune old backups to maintain max backup count\n\t */\n\tprivate async pruneBackups(): Promise<void> {\n\t\ttry {\n\t\t\tconst backups = await this.listBackups();\n\n\t\t\tif (backups.length > this.maxBackups) {\n\t\t\t\tconst toDelete = backups.slice(this.maxBackups);\n\n\t\t\t\tfor (const backup of toDelete) {\n\t\t\t\t\tawait fs.unlink(path.join(this.backupDir, backup));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error: any) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/workflow/managers/workflow-state-manager.ts#L213-L249","documentation":"restoreBackup() reads a backup file, JSON.parses it into a WorkflowStateBackup, and writes its state back via save(). Any failure at any of those steps — missing backup file, corrupt backup JSON, or a save() failure — is wrapped as 'Failed to restore backup: <cause>'.","triggerScenarios":"Calling restoreBackup(fileName) with a backup file that does not exist (ENOENT), contains truncated/invalid JSON (SyntaxError from JSON.parse), or whose inner save() fails (disk/permission issues, error 241).","commonSituations":"Restoring from a backup list captured before a prune removed the file; backup interrupted mid-write leaving truncated JSON; manual edits corrupting the backup; backup produced by an older schema that save() cannot persist.","solutions":["Read the cause after the colon: ENOENT means the backup name is wrong; SyntaxError means corrupt JSON; 'Failed to save workflow state' means the write step failed.","Run listBackups() to confirm the exact backup filename exists before restoring.","If JSON is corrupt, choose a different (older) backup file.","Validate the backup's JSON manually (jq <file>) to inspect damage.","Fix filesystem permissions/space if the underlying save() failed."],"exampleFix":"// before\nawait manager.restoreBackup('state-backup-2026-08-27T10.json'); // guess\n// after\nconst backups = await manager.listBackups();\nif (backups.includes('state-backup-2026-08-27T10.json')) {\n  await manager.restoreBackup('state-backup-2026-08-27T10.json');\n}","handlingStrategy":"validation","validationCode":"import { access } from 'fs/promises';\nconst backupPath = path.join(backupDir, fileName);\nawait access(backupPath); // throws ENOENT early if backup missing\nconst content = await readFile(backupPath, 'utf-8');\nJSON.parse(content); // throws SyntaxError early if corrupt\nif (!('state' in JSON.parse(content))) throw new Error('backup missing state');","typeGuard":"function isWorkflowStateBackup(v) {\n  return v !== null && typeof v === 'object'\n    && 'state' in v\n    && typeof v.state === 'object'\n    && v.state !== null;\n}","tryCatchPattern":"try {\n  await manager.restoreBackup(fileName);\n} catch (e) {\n  if (/ENOENT/.test(e.message)) {\n    const alt = (await manager.listBackups())[0];\n    if (alt) await manager.restoreBackup(alt);\n  } else throw e;\n}","preventionTips":["Always enumerate backups with listBackups() before restoring","Validate backup JSON (jq or JSON.parse) after any interrupted write","Keep several backup generations; never rely on a single file","Verify backup schema (has .state) before restore"],"tags":["json","backup","restore","workflow"],"backgroundTag":"corrupt-backup-file","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}