{"record":{"id":"3b2ceddbdf23c320","repo":"affaan-m/ECC","slug":"projectroot-or-reporoot-is-required-for-project-in","errorCode":null,"errorMessage":"projectRoot or repoRoot is required for project install targets","messagePattern":"projectRoot or repoRoot is required for project install targets","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install-targets/helpers.js","lineNumber":54,"sourceCode":"\n  for (const [prefix, ownerTarget] of Object.entries(PLATFORM_SOURCE_PATH_OWNERS)) {\n    if (normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`)) {\n      return ownerTarget !== adapterTarget;\n    }\n  }\n\n  return false;\n}\n\nfunction resolveBaseRoot(scope, input = {}) {\n  if (scope === 'home') {\n    return input.homeDir || os.homedir();\n  }\n\n  if (scope === 'project') {\n    const projectRoot = input.projectRoot || input.repoRoot;\n    if (!projectRoot) {\n      throw new Error('projectRoot or repoRoot is required for project install targets');\n    }\n    return projectRoot;\n  }\n\n  throw new Error(`Unsupported install target scope: ${scope}`);\n}\n\nfunction buildValidationIssue(severity, code, message, extra = {}) {\n  return {\n    severity,\n    code,\n    message,\n    ...extra,\n  };\n}\n\nfunction listRelativeFiles(dirPath, prefix = '') {\n  if (!fs.existsSync(dirPath)) {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install-targets/helpers.js#L36-L72","documentation":"resolveBaseRoot in install-target helpers computes the root directory for project-scope install targets (where configs like project-level MCP or agent files are written). For scope 'project' it requires either projectRoot or repoRoot in the input; without either it cannot know where to place files and throws.","triggerScenarios":"baseRoot('project', input) is called with an input object lacking both projectRoot and repoRoot — e.g. an adapter or caller resolved the planning input without passing the repository root through.","commonSituations":"Invoking an install target adapter directly from a custom script without providing repoRoot; a code path that builds target input omitted projectRoot after a refactor; running the installer from a context where repoRoot detection failed.","solutions":["Pass `projectRoot` (or `repoRoot`) in the options/input to the install target call","If calling the installer CLI, run it from inside the target repository so repoRoot is resolved","Check your custom adapter/script to ensure it forwards repoRoot into the target planning input"],"exampleFix":"// before\nconst root = baseRoot('project', {});\n// after\nconst root = baseRoot('project', { repoRoot: process.cwd() });","handlingStrategy":"validation","validationCode":"// Ensure roots are provided before invoking project-scope targets\nfunction assertProjectRoot(input = {}) {\n  if (!input.projectRoot && !input.repoRoot) {\n    throw new Error('project install targets need projectRoot or repoRoot');\n  }\n}","typeGuard":"function hasProjectRoot(input) {\n  return typeof input === 'object' && input !== null\n    && (typeof input.projectRoot === 'string' || typeof input.repoRoot === 'string');\n}","tryCatchPattern":"try {\n  baseRoot('project', input);\n} catch (e) {\n  if (/projectRoot or repoRoot is required/.test(e.message)) {\n    input.repoRoot = process.cwd(); // or the resolved workspace root\n  } else throw e;\n}","preventionTips":["Always pass repoRoot when constructing target planning input for installers","Resolve repoRoot once (git root or cwd) and thread it through all adapter calls","Add a startup assertion that repoRoot is set before any install operations"],"tags":["install-target","config","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}