{"record":{"id":"c99b5f9b065ce5c8","repo":"mastra-ai/mastra","slug":"enotdir","errorCode":"ENOTDIR","errorMessage":"Path is not a directory: ${path}","messagePattern":"Path is not a directory: (.+?)","errorType":"exception","errorClass":"NotDirectoryError","httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/filesystem/local-filesystem.ts","lineNumber":425,"sourceCode":"    }\n  }\n\n  async writeFile(inputPath: string, content: FileContent, options?: WriteOptions): Promise<void> {\n    const contentSize = Buffer.isBuffer(content) ? content.length : content.length;\n    this.logger.debug('Writing file', { path: inputPath, size: contentSize, recursive: options?.recursive });\n    await this.ensureReady();\n    this.assertWritable('writeFile');\n    const absolutePath = this.resolvePath(inputPath);\n    await this.assertPathContained(absolutePath);\n\n    // When recursive is explicitly false, verify parent directory exists\n    if (options?.recursive === false) {\n      const dir = nodePath.dirname(absolutePath);\n      const parentPath = nodePath.dirname(inputPath);\n      try {\n        const stat = await fs.stat(dir);\n        if (!stat.isDirectory()) {\n          throw new NotDirectoryError(parentPath);\n        }\n      } catch (error: unknown) {\n        if (error instanceof NotDirectoryError) throw error;\n        if (isEnoentError(error)) {\n          throw new DirectoryNotFoundError(parentPath);\n        }\n        throw error;\n      }\n    }\n\n    if (options?.recursive !== false) {\n      const dir = nodePath.dirname(absolutePath);\n      await fs.mkdir(dir, { recursive: true });\n    }\n\n    // Optimistic concurrency: reject if file was modified since caller last read it\n    if (options?.expectedMtime) {\n      try {","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/filesystem/local-filesystem.ts#L407-L443","documentation":"writeFile throws NotDirectoryError (code ENOTDIR) when options.recursive === false and the parent directory of the target path exists but is a regular file, not a directory. In non-recursive mode the library requires the immediate parent to be an existing directory; anything else is rejected before writing. (If the parent is missing entirely you get DirectoryNotFoundError instead.)","triggerScenarios":"writeFile('a/b.txt', data, { recursive: false }) where 'a' is an existing file; path segments colliding, e.g. a file named 'data' already exists and you write 'data/child.txt'; passing recursive: false explicitly when the caller assumed directories are auto-created.","commonSituations":"A previously written file occupies the name now used as a directory; workspace was seeded with a flat file layout that conflicts with nested paths; copy-pasted options keeping recursive: false from a strict-mode call.","solutions":["Remove recursive: false (or set recursive: true) so missing parent directories are created automatically — this is the default.","Rename/delete the file that is blocking the directory name, then write again.","Verify with stat that each path segment used as a directory is actually a directory.","Choose a target path whose parent is a real directory."],"exampleFix":"// before\nawait fs.writeFile('data/child.txt', 'x', { recursive: false }); // ENOTDIR if 'data' is a file\n// after\nawait fs.writeFile('data/child.txt', 'x'); // recursive defaults to true; or free the 'data' name first","handlingStrategy":"validation","validationCode":"const parent = nodePath.posix.dirname(p);\nconst s = await ws.stat(parent);\nif (s.type !== 'directory') {\n  throw new Error(`${parent} is not a directory; fix the path or enable recursive writes`);\n}","typeGuard":"import { NotDirectoryError } from '@mastra/core/workspace/errors';\nfunction isNotDirectoryError(e: unknown): e is NotDirectoryError {\n  return e instanceof NotDirectoryError ||\n    (e instanceof Error && 'code' in e && (e as { code?: string }).code === 'ENOTDIR');\n}","tryCatchPattern":"try {\n  await ws.writeFile(p, data, { recursive: false });\n} catch (e) {\n  if (isNotDirectoryError(e)) {\n    await ws.writeFile(p, data); // fall back to recursive (auto-mkdir)\n    return;\n  }\n  throw e;\n}","preventionTips":["Only use recursive: false when you truly need strict behavior; the default creates parents safely.","Keep file and directory names from colliding in your layout conventions.","Stat path segments that double as names before using them as directories.","Reserve recursive: false for guarded internals, not for paths derived from user input."],"tags":["filesystem","enotdir","parent-path"],"backgroundTag":"enotdir-path-component","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}