{"record":{"id":"62c16d8e6ed356a8","repo":"eyaltoledano/claude-task-master","slug":"projectroot-is-required-for-resolvetag","errorCode":null,"errorMessage":"projectRoot is required for resolveTag","messagePattern":"projectRoot is required for resolveTag","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/modules/utils.js","lineNumber":1809,"sourceCode":"\t\t// Ignore errors, use hardcoded default\n\t}\n\n\t// Final fallback\n\treturn 'master';\n}\n\n/**\n * Resolves the tag to use based on options\n * @param {Object} options - Options object\n * @param {string} options.projectRoot - The project root directory (required)\n * @param {string} [options.tag] - Explicit tag to use\n * @returns {string} The resolved tag name\n */\nfunction resolveTag(options = {}) {\n\tconst { projectRoot, tag } = options;\n\n\tif (!projectRoot) {\n\t\tthrow new Error('projectRoot is required for resolveTag');\n\t}\n\n\t// If explicit tag provided, use it\n\tif (tag) {\n\t\treturn tag;\n\t}\n\n\t// Otherwise get current tag from state/config\n\treturn getCurrentTag(projectRoot);\n}\n\n/**\n * Gets the tasks array for a specific tag from tagged tasks.json data\n * @param {Object} data - The parsed tasks.json data (after migration)\n * @param {string} tagName - The tag name to get tasks for\n * @returns {Array} The tasks array for the specified tag, or empty array if not found\n */\nfunction getTasksForTag(data, tagName) {","sourceCodeStart":1791,"sourceCodeEnd":1827,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/utils.js#L1791-L1827","documentation":"resolveTag determines the effective tag from options ({projectRoot, tag}), requiring projectRoot because it may need to read state.json/config to resolve the current tag. It throws when projectRoot is absent, even if an explicit tag is supplied (the check precedes tag handling).","triggerScenarios":"Calling resolveTag({}) or resolveTag({ tag: 'master' }) without projectRoot from API/MCP code that skipped root resolution.","commonSituations":"Integrations hardcoding a tag but forgetting projectRoot, wrappers around readJSON/writeJSON constructing options dynamically where projectRoot ends up undefined, or tests calling resolveTag with partial options.","solutions":["Always include projectRoot in the options object: resolveTag({ projectRoot, tag })","Obtain projectRoot via findProjectRoot() before building options","If only the explicit tag matters, return the tag directly in your caller instead of invoking resolveTag without a root"],"exampleFix":"// before\nresolveTag({ tag: 'master' });\n// after\nresolveTag({ projectRoot: '/path/to/project', tag: 'master' });","handlingStrategy":"validation","validationCode":"const opts = { projectRoot: findProjectRoot(), tag: explicitTag };\nif (!opts.projectRoot) throw new Error('resolveTag requires a project root');\nconst tag = resolveTag(opts);","typeGuard":"const validTagOptions = (o) => !!o && typeof o === 'object' && typeof o.projectRoot === 'string' && o.projectRoot.trim() !== '';","tryCatchPattern":"try {\n  const tag = resolveTag(options);\n} catch (e) {\n  if (e.message === 'projectRoot is required for resolveTag') {\n    // supply explicit tag or resolve projectRoot first\n  } else throw e;\n}","preventionTips":["Build options objects centrally so projectRoot is always set","Pass { projectRoot, tag } together from callers","Assert projectRoot presence in wrapper functions before tag resolution","Default to findProjectRoot() when callers omit the root"],"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"}