{"record":{"id":"abf102aa840099fd","repo":"eyaltoledano/claude-task-master","slug":"task-id-is-required","errorCode":null,"errorMessage":"Task ID is required","messagePattern":"Task ID is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/common/interfaces/storage.interface.ts","lineNumber":453,"sourceCode":"\t * @param originalPath - Original file path\n\t * @returns Backup file path with timestamp\n\t */\n\tprotected generateBackupPath(originalPath: string): string {\n\t\tconst timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n\t\tconst parts = originalPath.split('.');\n\t\tconst extension = parts.pop();\n\t\tconst baseName = parts.join('.');\n\t\treturn `${baseName}.backup.${timestamp}.${extension}`;\n\t}\n\n\t/**\n\t * Utility method to validate task data before storage operations\n\t * @param task - Task to validate\n\t * @throws Error if task is invalid\n\t */\n\tprotected validateTask(task: Task): void {\n\t\tif (!task.id) {\n\t\t\tthrow new Error('Task ID is required');\n\t\t}\n\t\tif (!task.title) {\n\t\t\tthrow new Error('Task title is required');\n\t\t}\n\t\tif (!task.description) {\n\t\t\tthrow new Error('Task description is required');\n\t\t}\n\t\tif (!task.status) {\n\t\t\tthrow new Error('Task status is required');\n\t\t}\n\t}\n\n\t/**\n\t * Utility method to sanitize tag names for file system safety\n\t * @param tag - Tag name to sanitize\n\t * @returns Sanitized tag name\n\t */\n\tprotected sanitizeTag(tag: string): string {","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/common/interfaces/storage.interface.ts#L435-L471","documentation":"The storage layer's validateTask guard runs before storage operations and requires a Task to have id, title, description, and status. This error is thrown when a task object with a missing/empty `id` is passed to a create/update/delete storage method, preventing corrupt or unaddressable records from entering storage.","triggerScenarios":"Calling storage.save/update with a Task built without an id (undefined, null, or empty string); deserialization dropping the id field; constructing a new Task manually and forgetting to assign the id.","commonSituations":"Mapping external data (imports, API payloads) into Task objects without normalizing ids; schema migrations leaving legacy rows/objects without ids; tests constructing partial Task fixtures.","solutions":["Assign a valid id before the storage call (generate one via your id scheme, e.g. numeric or string id).","Validate/normalize incoming payloads to ensure `id` is present before mapping to Task.","Check the deserialization path (JSON parse/mapper) isn't omitting the id field.","Update Task fixtures/factories to always include id."],"exampleFix":"// before\nawait storage.saveTask({ title: 'Fix bug', description: '...', status: 'pending' });\n// after\nawait storage.saveTask({ id: nextId(), title: 'Fix bug', description: '...', status: 'pending' });","handlingStrategy":"validation","validationCode":"function assertTaskBasics(t) { if (!t.id) throw new Error('Task must have an id before storage'); if (!t.title) throw new Error('Task must have a title'); if (!t.description) throw new Error('Task must have a description'); if (!t.status) throw new Error('Task must have a status'); }","typeGuard":"function isStorableTask(t) { return typeof t?.id === 'string' && t.id.length > 0 || (typeof t?.id === 'number' && Number.isFinite(t.id)); }","tryCatchPattern":"try { await storage.saveTask(task); } catch (e) { if (e.message === 'Task ID is required') { throw new InvalidTaskError('id', task); } throw e; }","preventionTips":["Generate ids in a Task factory so raw objects never reach storage","Validate external payloads before mapping to Task","Keep deserializers strict about required fields","Use typed constructors rather than object literals"],"tags":["validation","storage","task","precondition"],"backgroundTag":"missing-required-field","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}