{"record":{"id":"68e85a54d059db50","repo":"modelcontextprotocol/servers","slug":"parent-directory-does-not-exist-path-dirname-ab","errorCode":null,"errorMessage":"Parent directory does not exist: ${path.dirname(absolute)}","messagePattern":"Parent directory does not exist: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/filesystem/lib.ts","lineNumber":177,"sourceCode":"\n  // Security: Handle symlinks by checking their real path to prevent symlink attacks\n  // This prevents attackers from creating symlinks that point outside allowed directories\n  try {\n    const realPath = await fs.realpath(absolute);\n    const normalizedReal = normalizePath(realPath);\n    if (!isPathWithinAllowedDirectories(normalizedReal, allowedDirectories)) {\n      throw new Error(`Access denied - symlink target outside allowed directories: ${realPath} not in ${allowedDirectories.join(', ')}`);\n    }\n    return realPath;\n  } catch (error) {\n    // Security: For new files that don't exist yet, verify parent directory\n    // This ensures we can't create files in unauthorized locations\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      try {\n        return await resolveUnicodeEquivalentPath(absolute);\n      } catch (resolutionError) {\n        if ((resolutionError as NodeJS.ErrnoException).code === 'ENOENT') {\n          throw new Error(`Parent directory does not exist: ${path.dirname(absolute)}`);\n        }\n        throw resolutionError;\n      }\n    }\n    throw error;\n  }\n}\n\n\n// File Operations\nexport async function getFileStats(filePath: string): Promise<FileInfo> {\n  const stats = await fs.stat(filePath);\n  return {\n    size: stats.size,\n    created: stats.birthtime,\n    modified: stats.mtime,\n    accessed: stats.atime,\n    isDirectory: stats.isDirectory(),","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/modelcontextprotocol/servers/blob/579c3903f30044eb702a599a74b3ae77588e722e/src/filesystem/lib.ts#L159-L195","documentation":"When the requested path does not exist (realpath throws ENOENT), validatePath falls back to resolveUnicodeEquivalentPath to support mkdir -p style creation. If that fallback also fails with ENOENT, the nearest existing ancestor could not be resolved — meaning the parent directory chain is missing — so this error is thrown instead of silently creating directories in the wrong place.","triggerScenarios":"create_directory or write-style calls targeting '/allowed/a/b/newdir' where the parent '/allowed/a/b' (or an earlier ancestor) does not exist, or where a symlinked ancestor chain is broken.","commonSituations":"Typos in the parent directory name; assuming the tool creates intermediate directories; a directory deleted between planning and execution; Unicode-normalized parents that fail to match (leading to nested ENOENT).","solutions":["Create the parent directory chain first (create_directory on the parent, then the target)","Fix the typo/incorrect parent path in the request","Verify each ancestor exists with list_directory or get_file_info before creating children"],"exampleFix":"// before: parents missing\nawait create_directory('/allowed/projects/app/src'); // ENOENT at 'app'\n// after: create incrementally\nawait create_directory('/allowed/projects/app');\nawait create_directory('/allowed/projects/app/src');","handlingStrategy":"try-catch","validationCode":"const parent = path.dirname(p);\ntry { await fs.access(parent); } catch {\n  throw new Error(`Create parent ${parent} before ${p}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await create_directory(p);\n} catch (err) {\n  if (err.message.startsWith('Parent directory does not exist')) {\n    await create_directory(err.message.split(': ')[1]); // create parent, then retry\n    await create_directory(p);\n  } else throw err;\n}","preventionTips":["Ensure every ancestor directory exists before creating children (mkdir -p semantics manually)","Validate parent paths with get_file_info/list_directory first","Check for typos in directory names","Re-verify directories still exist after external deletions or rebases"],"tags":["filesystem","missing-directory","path-resolution","enoent"],"backgroundTag":"missing-parent-directory","analyzedSha":"579c3903f30044eb702a599a74b3ae77588e722e","analyzedAt":"2026-09-01T06:06:22.520Z","contentChangedAt":"2026-09-01T06:06:22.520Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}