{"record":{"id":"8fdf11ef9ee7c5ce","repo":"eyaltoledano/claude-task-master","slug":"tag-name-can-only-contain-letters-numbers-hyphen","errorCode":null,"errorMessage":"Tag name can only contain letters, numbers, hyphens, and underscores","messagePattern":"Tag name can only contain letters, numbers, hyphens, and underscores","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/modules/task-manager/tag-management.js","lineNumber":91,"sourceCode":"\t\t\tthrow new Error(remoteResult.message || 'Remote tag creation failed');\n\t\t}\n\t\tif (outputFormat === 'json') {\n\t\t\treturn remoteResult;\n\t\t}\n\t\t// For text output, the bridge already displayed the message\n\t\treturn remoteResult;\n\t}\n\n\t// Otherwise, continue with file-based logic below\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// Validate tag name format (alphanumeric, hyphens, underscores only)\n\t\tif (!/^[a-zA-Z0-9_-]+$/.test(tagName)) {\n\t\t\tthrow new Error(\n\t\t\t\t'Tag name can only contain letters, numbers, hyphens, and underscores'\n\t\t\t);\n\t\t}\n\n\t\t// Reserved tag names\n\t\tconst reservedNames = ['master', 'main', 'default'];\n\t\tif (reservedNames.includes(tagName.toLowerCase())) {\n\t\t\tthrow new Error(`\"${tagName}\" is a reserved tag name`);\n\t\t}\n\n\t\tlogFn.info(`Creating new 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","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/task-manager/tag-management.js#L73-L109","documentation":"createTag enforces a tag-name format of /^[a-zA-Z0-9_-]+$/ — letters, numbers, hyphens, and underscores only. Names containing spaces, slashes, dots, unicode, or other special characters are rejected because tags are used as JSON keys and path/branch-safe identifiers.","triggerScenarios":"Calling createTag with names like 'my tag', 'v1.0', 'feature/x', 'réparation', or any name with punctuation outside [A-Za-z0-9_-].","commonSituations":"Deriving tag names from branch names ('feature/login'), version strings ('2.1.0'), or user input with spaces; pasting names with trailing whitespace.","solutions":["Sanitize the name: replace invalid characters with hyphens or underscores","Lowercase/kebab-case the name before calling createTag","Trim whitespace from user-provided or branch-derived names"],"exampleFix":"// before\nawait createTag(tasksPath, 'feature/login v2');\n// after\nconst safe = 'feature/login v2'.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-|-$/g, '');\nawait createTag(tasksPath, safe); // feature-login-v2","handlingStrategy":"validation","validationCode":"if (!/^[a-zA-Z0-9_-]+$/.test(tagName)) {\n  throw new Error(`Invalid tag name '${tagName}'; use letters, numbers, hyphens, underscores only`);\n}","typeGuard":"function isSafeTagName(name) {\n  return typeof name === 'string' && /^[a-zA-Z0-9_-]+$/.test(name);\n}","tryCatchPattern":"try {\n  await createTag(tasksPath, tagName, {});\n} catch (err) {\n  if (err.message.includes('can only contain letters, numbers, hyphens')) {\n    const safe = tagName.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');\n    await createTag(tasksPath, safe, {});\n  } else throw err;\n}","preventionTips":["Always sanitize derived names (branches, versions) before creating tags","Adopt a kebab-case naming convention for tags","Trim whitespace from all user-supplied names","Show the allowed pattern in UI prompts so users type valid names"],"tags":["validation","naming","tagging"],"backgroundTag":"invalid-name-format","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}