{"record":{"id":"613461821e1f9339","repo":"eyaltoledano/claude-task-master","slug":"cannot-delete-the-master-tag","errorCode":null,"errorMessage":"Cannot delete the \"master\" tag","messagePattern":"Cannot delete the \"master\" tag","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/modules/task-manager/tag-management.js","lineNumber":273,"sourceCode":"\n\t// Create a consistent logFn object regardless of context\n\tconst logFn = mcpLog || {\n\t\tinfo: (...args) => log('info', ...args),\n\t\twarn: (...args) => log('warn', ...args),\n\t\terror: (...args) => log('error', ...args),\n\t\tdebug: (...args) => log('debug', ...args),\n\t\tsuccess: (...args) => log('success', ...args)\n\t};\n\n\ttry {\n\t\t// Validate tag name\n\t\tif (!tagName || typeof tagName !== 'string') {\n\t\t\tthrow new Error('Tag name is required and must be a string');\n\t\t}\n\n\t\t// Prevent deletion of master tag\n\t\tif (tagName === 'master') {\n\t\t\tthrow new Error('Cannot delete the \"master\" tag');\n\t\t}\n\n\t\tlogFn.info(`Deleting tag: ${tagName}`);\n\n\t\t// Read current tasks data\n\t\tconst data = readJSON(tasksPath, projectRoot);\n\t\tif (!data) {\n\t\t\tthrow new Error(`Could not read tasks file at ${tasksPath}`);\n\t\t}\n\n\t\t// Use raw tagged data for tag operations - ensure we get the actual tagged structure\n\t\tlet rawData;\n\t\tif (data._rawTaggedData) {\n\t\t\t// If we have _rawTaggedData, use it (this is the clean tagged structure)\n\t\t\trawData = data._rawTaggedData;\n\t\t} else if (data.tasks && !data.master) {\n\t\t\t// This is legacy format - create a master tag structure\n\t\t\trawData = {","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/task-manager/tag-management.js#L255-L291","documentation":"The 'master' tag is the default/root tag in task-master's tagged tasks.json format. deleteTag() hard-blocks deleting it because removing it would leave the project with no default tag and break the current-tag pointer. This is an intentional protection, not a bug.","triggerScenarios":"Calling deleteTag(tasksPath, 'master', ...) directly, or a CLI/MCP wrapper forwarding 'master' as the tag name to `task-master delete-tag master`.","commonSituations":"Users trying to 'clean up' their tasks file by removing the default tag, batch-delete scripts iterating all tags including master, or automation that forgot to filter out 'master' from a tag list.","solutions":["Do not delete 'master'; delete the specific tag you intended instead.","If master's contents are unwanted, switch to a new tag (useTag) and delete tasks individually, or clear tasks within master.","If you truly need a fresh start, create a new tagged tasks.json rather than deleting master from an existing one."],"exampleFix":"// before\nawait deleteTag(tasksPath, 'master', { yes: true }, context);\n// after\nconst target = tag === 'master' ? null : tag;\nif (!target) throw new Error('Refusing to delete the master tag; pick another tag');\nawait deleteTag(tasksPath, target, { yes: true }, context);","handlingStrategy":"validation","validationCode":"if (tagName === 'master') {\n  throw new Error('The master tag cannot be deleted; choose another tag');\n}","typeGuard":null,"tryCatchPattern":"// Treat as expected refusal, not a crash\ntry {\n  await deleteTag(tasksPath, tag, opts, ctx);\n} catch (e) {\n  if (e.message.includes('master')) {\n    console.warn('Skipping protected master tag');\n    return;\n  }\n  throw e;\n}","preventionTips":["Filter 'master' out of any batch tag-deletion lists.","Check the target tag name in CLI wrappers before invoking deleteTag.","Document that master is immutable in team runbooks/scripts."],"tags":["tag-management","protected-resource","validation"],"backgroundTag":"protected-tag-deletion","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}