{"record":{"id":"67221c4be98d3372","repo":"eyaltoledano/claude-task-master","slug":"targetpath-must-end-with-gitignore","errorCode":null,"errorMessage":"targetPath must end with .gitignore","messagePattern":"targetPath must end with \\.gitignore","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/utils/manage-gitignore.js","lineNumber":153,"sourceCode":"\t\t\tlines.push('');\n\t\t}\n\t}\n}\n\n/**\n * Validates input parameters\n * @param {string} targetPath - Path to .gitignore file\n * @param {string} content - Template content\n * @param {boolean} storeTasksInGit - Storage preference\n * @throws {Error} If validation fails\n */\nfunction validateInputs(targetPath, content, storeTasksInGit) {\n\tif (!targetPath || typeof targetPath !== 'string') {\n\t\tthrow new Error('targetPath must be a non-empty string');\n\t}\n\n\tif (!targetPath.endsWith('.gitignore')) {\n\t\tthrow new Error('targetPath must end with .gitignore');\n\t}\n\n\tif (!content || typeof content !== 'string') {\n\t\tthrow new Error('content must be a non-empty string');\n\t}\n\n\tif (typeof storeTasksInGit !== 'boolean') {\n\t\tthrow new Error('storeTasksInGit must be a boolean');\n\t}\n}\n\n/**\n * Creates a new .gitignore file from template\n * @param {string} targetPath - Path to create file at\n * @param {string[]} templateLines - Adjusted template lines\n * @param {function} log - Logging function\n */\nfunction createNewGitignoreFile(targetPath, templateLines, log) {","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/src/utils/manage-gitignore.js#L135-L171","documentation":"validateInputs requires the target path to actually end with '.gitignore' so the module never writes template content to the wrong file. It throws when targetPath is a valid string but lacks the .gitignore suffix.","triggerScenarios":"Calling manageGitignoreFile with paths like 'path/to/.gitignore.txt', 'gitignore', a directory path 'repo/', or a file such as '.gitignore_global' — anything whose endsWith('.gitignore') check fails.","commonSituations":"Passing the project root or a directory instead of the file path; typos in the filename; using an alternate ignore file name that the validator does not accept; concatenating paths incorrectly so the suffix is lost.","solutions":["Point targetPath at the exact file: path.join(projectRoot, '.gitignore')","Remove stray extensions from the path string","If managing a different ignore file, copy its contents rather than routing it through this API"],"exampleFix":"// before\nmanageGitignoreFile('myrepo/.gitignore.bak', content, true);\n// after\nmanageGitignoreFile('myrepo/.gitignore', content, true);","handlingStrategy":"validation","validationCode":"if (typeof targetPath !== 'string' || !targetPath.endsWith('.gitignore')) {\n  throw new TypeError(`targetPath must end with .gitignore, got: ${targetPath}`);\n}","typeGuard":"const isGitignoreFile = (v) => typeof v === 'string' && v.endsWith('.gitignore');","tryCatchPattern":"try {\n  manageGitignoreFile(targetPath, content, storeTasksInGit);\n} catch (err) {\n  if (err.message === 'targetPath must end with .gitignore') {\n    manageGitignoreFile(path.join(path.dirname(targetPath), '.gitignore'), content, storeTasksInGit);\n  } else throw err;\n}","preventionTips":["Always construct the path as path.join(root, '.gitignore') instead of hand-writing it","Check the suffix with endsWith('.gitignore') before calling","Do not pass directories or backup/variant filenames to this API"],"tags":["validation","arguments","git"],"backgroundTag":"invalid-argument-type","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}