{"record":{"id":"5fcf345653a7472a","repo":"eyaltoledano/claude-task-master","slug":"directory-create-failed","errorCode":"DIRECTORY_CREATE_FAILED","errorMessage":"Failed to create output directory ${outputDir}: ${error.message}","messagePattern":"Failed to create output directory (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mcp-server/src/core/direct-functions/parse-prd.js","lineNumber":112,"sourceCode":"\t\tlogWrapper.error(errorMsg);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: 'FILE_NOT_FOUND', message: errorMsg }\n\t\t};\n\t}\n\n\tconst outputDir = path.dirname(outputPath);\n\ttry {\n\t\tif (!fs.existsSync(outputDir)) {\n\t\t\tlogWrapper.info(`Creating output directory: ${outputDir}`);\n\t\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t\t}\n\t} catch (error) {\n\t\tconst errorMsg = `Failed to create output directory ${outputDir}: ${error.message}`;\n\t\tlogWrapper.error(errorMsg);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: 'DIRECTORY_CREATE_FAILED', message: errorMsg }\n\t\t};\n\t}\n\n\tlet numTasks = getDefaultNumTasks(projectRoot);\n\tif (numTasksArg) {\n\t\tnumTasks =\n\t\t\ttypeof numTasksArg === 'string' ? parseInt(numTasksArg, 10) : numTasksArg;\n\t\tif (Number.isNaN(numTasks) || numTasks < 0) {\n\t\t\t// Ensure positive number\n\t\t\tnumTasks = getDefaultNumTasks(projectRoot); // Fallback to default if parsing fails or invalid\n\t\t\tlogWrapper.warn(\n\t\t\t\t`Invalid numTasks value: ${numTasksArg}. Using default: ${numTasks}`\n\t\t\t);\n\t\t}\n\t}\n\n\tif (append) {\n\t\tlogWrapper.info('Append mode enabled.');","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/mcp-server/src/core/direct-functions/parse-prd.js#L94-L130","documentation":"Before parsing, parsePRDDirect ensures the output directory (dirname of the resolved tasks.json output path) exists, creating it recursively with fs.mkdirSync (parse-prd.js:101-114). If directory creation fails — permissions, read-only filesystem, path is actually a file — it returns DIRECTORY_CREATE_FAILED with the OS error message.","triggerScenarios":"The parent path segment of `output` is an existing regular file (mkdirSync hits EEXIST/ENOTDIR); the process lacks write permission on the target directory (EACCES/EPERM); the filesystem is read-only (EROFS, common in containers); disk full (ENOSPC).","commonSituations":"Output path pointing at an existing file instead of a directory path; running the MCP server as a user without write access to the project; Docker volumes mounted read-only; a `output` value that accidentally overrode the tasks.json file path with a directory-style value.","solutions":["Read the OS error in the message: EACCES/EPERM → fix permissions; ENOTDIR/EEXIST → a file occupies part of the path; EROFS → remount writable.","Verify the `output` argument: it should be the tasks.json file path (its dirname will be created), not a path colliding with an existing file.","Ensure the MCP server process user can write to projectRoot (chown/chmod or run with correct user).","Pre-create the directory manually (mkdir -p) and confirm it succeeds before retrying."],"exampleFix":"// before\nawait parsePRDDirect({ projectRoot: '/proj', input: prd, output: '/proj/.taskmaster/tasks' }, log);\n// tasks exists as a FILE -> DIRECTORY_CREATE_FAILED\n\n// after\nawait parsePRDDirect({ projectRoot: '/proj', input: prd, output: '/proj/.taskmaster/tasks/tasks.json' }, log);","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst path = require('path');\nfunction outputDirCreatable(outputPath) {\n  const dir = path.dirname(outputPath);\n  if (fs.existsSync(dir) && !fs.statSync(dir).isDirectory()) return false;\n  try { fs.accessSync(path.dirname(dir), fs.constants.W_OK); return true; }\n  catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"const result = await parsePRDDirect({ projectRoot, input, output }, log);\nif (!result.success && result.error?.code === 'DIRECTORY_CREATE_FAILED') {\n  console.error('Cannot create output dir:', result.error.message); // EACCES/ENOTDIR/EROFS\n}","preventionTips":["Point `output` at the tasks.json file path, not a path occupied by an existing file.","Run the MCP server with a user that has write access to projectRoot.","Avoid read-only volume mounts for the output location.","Pre-create the directory with mkdir -p and check it succeeds."],"tags":["mcp","filesystem","permissions","directory"],"backgroundTag":"directory-create-failed","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}