eyaltoledano/claude-task-master · error · Error
Tag "${newName}" already exists
Error message
Tag "${newName}" already exists What it means
renameTag() refuses to rename to a tag name that already exists in the tagged data, since two tags cannot share one key. This prevents silently overwriting an existing tag's tasks. Delete the conflicting tag or choose another name.
Source
Thrown at scripts/modules/task-manager/tag-management.js:1001
logFn.info(`Renaming tag from "${oldName}" to "${newName}"`);
// Read current tasks data
const data = readJSON(tasksPath, projectRoot);
if (!data) {
throw new Error(`Could not read tasks file at ${tasksPath}`);
}
// Use raw tagged data for tag operations
const rawData = data._rawTaggedData || data;
// Check if old tag exists
if (!rawData[oldName]) {
throw new Error(`Tag "${oldName}" does not exist`);
}
// Check if new tag name already exists
if (rawData[newName]) {
throw new Error(`Tag "${newName}" already exists`);
}
// Get current tag to check if we're renaming the active tag
const currentTag = getCurrentTag(projectRoot);
const isCurrentTag = currentTag === oldName;
// Rename the tag by copying data and deleting old
rawData[newName] = { ...rawData[oldName] };
// Update metadata if it exists
if (rawData[newName].metadata) {
rawData[newName].metadata.renamed = {
from: oldName,
date: new Date().toISOString()
};
}
delete rawData[oldName];View on GitHub (pinned to c0c98d367c)
Solutions
- Choose a unique target name that does not already exist in tasks.json
- Delete or rename the existing conflicting tag first (deleteTag / another renameTag call)
- Guard before calling: check the target key is absent in the parsed tasks.json data
- If data is left over from a failed rename, clean up the duplicate tag manually in tasks.json
Example fix
// before await renameTag(tasksPath, 'wip', 'in-progress'); // already exists // after const data = JSON.parse(fs.readFileSync(tasksPath, 'utf8')); if (data['in-progress']) await deleteTag(tasksPath, 'in-progress'); await renameTag(tasksPath, 'wip', 'in-progress');
Defensive patterns
Strategy: validation
Validate before calling
const data = JSON.parse(require('fs').readFileSync(tasksPath, 'utf8'));
if (Object.prototype.hasOwnProperty.call(data, newName)) {
throw new Error(`Target tag "${newName}" already exists; choose another name or delete it first`);
} Type guard
function tagIsFree(tasksData, name) {
return typeof name === 'string' && !Object.prototype.hasOwnProperty.call(tasksData, name);
} Try / catch
try {
await renameTag(tasksPath, oldName, newName);
} catch (err) {
if (err.message.includes('already exists')) {
console.error(`Tag "${newName}" is taken — pick a unique name or delete the existing tag`);
return;
}
throw err;
} Prevention
- Check target-name availability before renaming, especially in automated flows
- Generate unique names (suffix with date/timestamp) for scripted renames
- Clean up partial state if a previous rename/copy failed midway
- Delete unwanted tags with deleteTag before reusing their names
When it happens
Trigger: Calling renameTag(tasksPath, 'a', 'b') when a tag 'b' already exists; renaming a tag back to a name it previously held; bulk rename scripts producing colliding targets.
Common situations: Retry after a partially completed rename left both names present; users toggling between two names ('todo' <-> 'doing') without deleting; auto-generated names colliding with existing tags.
Related errors
- MFA_VERIFICATION_FAILED
- Failed to get brief creation URL
- Failed to initialize services: ${(error as Error).message}
- Invalid format: ${options.format}. Valid formats are: text,
- Failed to fetch tasks from any tag. First error: ${failedTag
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/d2e8d14dc236af5d.
Report an issue: GitHub.