{"record":{"id":"fb457c3411e28698","repo":"eyaltoledano/claude-task-master","slug":"validation-error-fb457c","errorCode":"VALIDATION_ERROR","errorMessage":"Tag ${tagName} already exists","messagePattern":"Tag (.+?) already exists","errorType":"exception","errorClass":"TaskMasterError","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts","lineNumber":632,"sourceCode":"\n\t/**\n\t * Create a new tag in the tasks.json file\n\t * Uses modifyJson for atomic read-modify-write to prevent lost updates\n\t */\n\tasync createTag(\n\t\ttagName: string,\n\t\toptions?: { copyFrom?: string; description?: string }\n\t): Promise<void> {\n\t\tconst filePath = this.pathResolver.getTasksPath();\n\n\t\ttry {\n\t\t\tawait this.fileOps.modifyJson(filePath, (existingData: any) => {\n\t\t\t\tconst format = this.formatHandler.detectFormat(existingData);\n\n\t\t\t\tif (format === 'legacy') {\n\t\t\t\t\t// Legacy format - add new tag key\n\t\t\t\t\tif (tagName in existingData) {\n\t\t\t\t\t\tthrow new TaskMasterError(\n\t\t\t\t\t\t\t`Tag ${tagName} already exists`,\n\t\t\t\t\t\t\tERROR_CODES.VALIDATION_ERROR\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Get tasks to copy if specified\n\t\t\t\t\tlet tasksToCopy: any[] = [];\n\t\t\t\t\tif (options?.copyFrom) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\toptions.copyFrom in existingData &&\n\t\t\t\t\t\t\texistingData[options.copyFrom].tasks\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\ttasksToCopy = JSON.parse(\n\t\t\t\t\t\t\t\tJSON.stringify(existingData[options.copyFrom].tasks)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts#L614-L650","documentation":"createTag refuses to create a tag whose name is already a key in the legacy-format tasks.json. It throws a TaskMasterError with code VALIDATION_ERROR so callers can distinguish it from generic failures. Tags are unique namespaces for task sets, so duplicate creation is treated as a validation problem, not a filesystem problem.","triggerScenarios":"storage.createTag('feature-x') when 'feature-x' already exists in tasks.json; re-running an idempotent-looking setup script twice; calling createTag with 'master' when the file already has a master key; a tag created by another process between your existence check and the create.","commonSituations":"CI pipelines that provision tags on every run without checking existence; team members both creating the same named tag; scripts that assume create is upsert; copy-pasted tag names differing only by case or whitespace confusion.","solutions":["List existing tags first (storage.getTagsWithStats()) and skip creation if the tag already exists.","Catch the TaskMasterError and check error.code === 'VALIDATION_ERROR' to treat duplicates as a no-op.","Use renameTag if the intent was to change an existing tag rather than create a new one.","Use copyTag from an existing tag if you wanted the tasks duplicated under a new name."],"exampleFix":"// before\nawait storage.createTag('feature-x');\n// after\nconst { tags } = await storage.getTagsWithStats();\nif (!tags.some((t) => t.name === 'feature-x')) {\n  await storage.createTag('feature-x');\n}","handlingStrategy":"try-catch","validationCode":"const { tags } = await storage.getTagsWithStats();\nif (tags.some((t) => t.name === tagName)) {\n  return; // already exists, skip creation\n}","typeGuard":"function tagExists(tagList: Array<{ name: string }>, name: string): tagList is Array<{ name: string }> & { found: true } {\n  return tagList.some((t) => t.name === name);\n}","tryCatchPattern":"import { TaskMasterError, ERROR_CODES } from '@tm/core';\ntry {\n  await storage.createTag(tagName);\n} catch (err) {\n  if (err instanceof TaskMasterError && err.code === ERROR_CODES.VALIDATION_ERROR) {\n    return; // duplicate tag — treat as success\n  }\n  throw err;\n}","preventionTips":["Make tag provisioning idempotent: check-then-create or catch VALIDATION_ERROR as a no-op.","List tags before creating in CI pipelines that run on every build.","Coordinate tag creation across team members/branches to avoid collisions.","Normalize tag names (trim, consistent casing) before passing to createTag."],"tags":["tag-management","duplicate","validation","file-storage"],"backgroundTag":"duplicate-resource-conflict","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}