eyaltoledano/claude-task-master · error
Task ID is required
Error message
Task ID is required
What it means
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.
Source
Thrown at packages/tm-core/src/common/interfaces/storage.interface.ts:453
* @param originalPath - Original file path
* @returns Backup file path with timestamp
*/
protected generateBackupPath(originalPath: string): string {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const parts = originalPath.split('.');
const extension = parts.pop();
const baseName = parts.join('.');
return `${baseName}.backup.${timestamp}.${extension}`;
}
/**
* Utility method to validate task data before storage operations
* @param task - Task to validate
* @throws Error if task is invalid
*/
protected validateTask(task: Task): void {
if (!task.id) {
throw new Error('Task ID is required');
}
if (!task.title) {
throw new Error('Task title is required');
}
if (!task.description) {
throw new Error('Task description is required');
}
if (!task.status) {
throw new Error('Task status is required');
}
}
/**
* Utility method to sanitize tag names for file system safety
* @param tag - Tag name to sanitize
* @returns Sanitized tag name
*/
protected sanitizeTag(tag: string): string {View on GitHub (pinned to c0c98d367c)
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.
Example fix
// before
await storage.saveTask({ title: 'Fix bug', description: '...', status: 'pending' });
// after
await storage.saveTask({ id: nextId(), title: 'Fix bug', description: '...', status: 'pending' }); Defensive patterns
Strategy: validation
Validate before calling
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'); } Type guard
function isStorableTask(t) { return typeof t?.id === 'string' && t.id.length > 0 || (typeof t?.id === 'number' && Number.isFinite(t.id)); } Try / catch
try { await storage.saveTask(task); } catch (e) { if (e.message === 'Task ID is required') { throw new InvalidTaskError('id', task); } throw e; } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Task title is required
- Task description is required
- Task status is required
- Task ${taskId} not found
- MFA_VERIFICATION_FAILED
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/abf102aa840099fd.
Report an issue: GitHub.