{"record":{"id":"1f710b2973587cae","repo":"eyaltoledano/claude-task-master","slug":"project-path-must-be-an-absolute-path","errorCode":null,"errorMessage":"Project path must be an absolute path","messagePattern":"Project path must be an absolute path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/git/adapters/git-adapter.ts","lineNumber":36,"sourceCode":"\n\t/**\n\t * Creates a new GitAdapter instance.\n\t *\n\t * @param {string} projectPath - Absolute path to the project directory\n\t * @throws {Error} If projectPath is invalid or not absolute\n\t *\n\t * @example\n\t * const git = new GitAdapter('/path/to/project');\n\t * await git.ensureGitRepository();\n\t */\n\tconstructor(projectPath: string) {\n\t\t// Validate project path\n\t\tif (!projectPath) {\n\t\t\tthrow new Error('Project path is required');\n\t\t}\n\n\t\tif (!path.isAbsolute(projectPath)) {\n\t\t\tthrow new Error('Project path must be an absolute path');\n\t\t}\n\n\t\t// Normalize path\n\t\tthis.projectPath = path.normalize(projectPath);\n\n\t\t// Initialize simple-git\n\t\tthis.git = simpleGit(this.projectPath);\n\t}\n\n\t/**\n\t * Checks if the current directory is a git repository.\n\t * Looks for .git directory or file (worktree/submodule).\n\t *\n\t * @returns {Promise<boolean>} True if in a git repository\n\t *\n\t * @example\n\t * const isRepo = await git.isGitRepository();\n\t * if (!isRepo) {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/git/adapters/git-adapter.ts#L18-L54","documentation":"Plain Error thrown by the GitAdapter constructor when projectPath is provided but not absolute (path.isAbsolute fails, e.g. './myproject' or 'myproject'). The adapter normalizes and stores the path and needs an absolute base for simple-git operations, so relative paths are rejected at construction.","triggerScenarios":"new GitAdapter('./repo'), new GitAdapter('~/project') (tilde is NOT expanded by path.isAbsolute on POSIX), or passing a path built from a relative CLI/config value.","commonSituations":"Users writing '~/myproject' in config expecting shell-style tilde expansion; passing relative paths from CWD-based tooling; constructing the adapter in a library where the caller's CWD differs from the project directory.","solutions":["Convert to absolute first: path.resolve(projectPath) or path.resolve(process.cwd(), projectPath)","Expand '~' explicitly with os.homedir() before constructing (path.isAbsolute does not expand tilde)","Fix config/CLI layers to store absolute paths","Reorder construction so the adapter is created after the project root is resolved"],"exampleFix":"// before\nconst git = new GitAdapter('~/projects/app'); // throws: not absolute\n// after\nimport * as os from 'os';\nconst p = config.projectPath.startsWith('~')\n  ? path.join(os.homedir(), config.projectPath.slice(1))\n  : path.resolve(config.projectPath);\nconst git = new GitAdapter(p);","handlingStrategy":"validation","validationCode":"import * as path from 'path';\nif (!path.isAbsolute(projectPath)) {\n  projectPath = path.resolve(process.cwd(), projectPath);\n}","typeGuard":"function isAbsolutePath(v: string): boolean {\n  return path.isAbsolute(v);\n}","tryCatchPattern":"try {\n  const git = new GitAdapter(projectPath);\n} catch (e) {\n  if (e.message === 'Project path must be an absolute path') {\n    const git = new GitAdapter(path.resolve(projectPath));\n  } else throw e;\n}","preventionTips":["Always path.resolve() user/config-supplied paths before constructing the adapter","Expand '~' with os.homedir() — path.isAbsolute does not handle tilde","Store absolute paths in config files, or resolve them relative to the config file location","Add an isAbsolute assertion in your own constructor/factory wrappers"],"tags":["git","validation","path","constructor"],"backgroundTag":"path-must-be-absolute","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}