{"record":{"id":"d844ba75d0208966","repo":"eyaltoledano/claude-task-master","slug":"projectroot-is-required-for-getcurrenttag","errorCode":null,"errorMessage":"projectRoot is required for getCurrentTag","messagePattern":"projectRoot is required for getCurrentTag","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/modules/utils.js","lineNumber":1763,"sourceCode":"\t}\n\tif (uniqueCurrencies.size > 1) {\n\t\taggregated.currency = 'Multiple'; // Mark if currencies actually differ\n\t} else if (uniqueCurrencies.size === 1) {\n\t\taggregated.currency = [...uniqueCurrencies][0];\n\t}\n\n\treturn aggregated;\n}\n\n/**\n * @deprecated Use TaskMaster.getCurrentTag() instead\n * Gets the current tag from state.json or falls back to defaultTag from config\n * @param {string} projectRoot - The project root directory (required)\n * @returns {string} The current tag name\n */\nfunction getCurrentTag(projectRoot) {\n\tif (!projectRoot) {\n\t\tthrow new Error('projectRoot is required for getCurrentTag');\n\t}\n\n\ttry {\n\t\t// Try to read current tag from state.json using fs directly\n\t\tconst statePath = path.join(projectRoot, '.taskmaster', 'state.json');\n\t\tif (fs.existsSync(statePath)) {\n\t\t\tconst rawState = fs.readFileSync(statePath, 'utf8');\n\t\t\tconst stateData = JSON.parse(rawState);\n\t\t\tif (stateData && stateData.currentTag) {\n\t\t\t\treturn stateData.currentTag;\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\t// Ignore errors, fall back to default\n\t}\n\n\t// Fall back to defaultTag from config using fs directly\n\ttry {","sourceCodeStart":1745,"sourceCodeEnd":1781,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/utils.js#L1745-L1781","documentation":"getCurrentTag reads .taskmaster/state.json under the project root to report the active tag, falling back to the configured defaultTag. Because it joins paths off projectRoot, the parameter is mandatory and the function throws immediately if it is missing.","triggerScenarios":"Calling getCurrentTag(undefined/null/'') — typically from programmatic code that resolved the project root elsewhere and passed nothing, or a caller that ran before root detection succeeded.","commonSituations":"Custom scripts or integrations calling the util directly without options, refactors removing root-resolution logic upstream, or embedding task-master in tools where cwd isn't a taskmaster project.","solutions":["Pass an explicit projectRoot string: getCurrentTag('/path/to/project')","Resolve the root first with findProjectRoot() and pass its result","Guard the call site to skip tag resolution when no root is available (use defaultTag instead)"],"exampleFix":"// before\nconst tag = getCurrentTag();\n// after\nconst tag = getCurrentTag(findProjectRoot() || process.cwd());","handlingStrategy":"validation","validationCode":"if (!projectRoot) throw new Error('projectRoot must be resolved before calling getCurrentTag');","typeGuard":"const hasRoot = (p) => typeof p === 'string' && p.trim() !== '';","tryCatchPattern":"try {\n  const tag = getCurrentTag(projectRoot);\n} catch (e) {\n  if (e.message === 'projectRoot is required for getCurrentTag') {\n    const tag = 'master'; // fallback default tag\n  } else throw e;\n}","preventionTips":["Always resolve project root (findProjectRoot) before tag APIs","Thread projectRoot through your integration's options explicitly","Unit-test tag helpers with explicit roots","Never call tag utilities with possibly-undefined roots"],"tags":["parameter-validation","project-root","tags"],"backgroundTag":"missing-required-parameter","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}