{"record":{"id":"2455e7ad91c71858","repo":"mastra-ai/mastra","slug":"eisdir","errorCode":"EISDIR","errorMessage":"Path is a directory: ${path}","messagePattern":"Path is a directory: (.+?)","errorType":"exception","errorClass":"IsDirectoryError","httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/filesystem/local-filesystem.ts","lineNumber":394,"sourceCode":"    const isWithinRoot = rootReals.some(\n      rootReal => targetReal === rootReal || targetReal.startsWith(rootReal + nodePath.sep),\n    );\n\n    if (!isWithinRoot) {\n      throw new PermissionError(absolutePath, 'access');\n    }\n  }\n\n  async readFile(inputPath: string, options?: ReadOptions): Promise<string | Buffer> {\n    this.logger.debug('Reading file', { path: inputPath, encoding: options?.encoding });\n    await this.ensureReady();\n    const absolutePath = this.resolvePath(inputPath);\n    await this.assertPathContained(absolutePath);\n\n    try {\n      const stats = await fs.stat(absolutePath);\n      if (stats.isDirectory()) {\n        throw new IsDirectoryError(inputPath);\n      }\n\n      if (options?.encoding) {\n        return await fs.readFile(absolutePath, { encoding: options.encoding });\n      }\n      return await fs.readFile(absolutePath);\n    } catch (error: unknown) {\n      if (error instanceof IsDirectoryError) throw error;\n      if (isEnoentError(error)) {\n        throw new FileNotFoundError(inputPath);\n      }\n      throw error;\n    }\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 });","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/filesystem/local-filesystem.ts#L376-L412","documentation":"readFile throws IsDirectoryError (code EISDIR) when the requested path resolves to a directory rather than a regular file. The stat happens after containment checks and before the actual fs.readFile, so directories are rejected with a clear typed error instead of the raw Node EISDIR. Use list/readdir-style APIs to inspect directories; readFile is for files only.","triggerScenarios":"workspace.filesystem.readFile('src') where src is a directory; passing a directory path to the 'content' helper; a path the caller assumed was a file (e.g. from a fuzzy name match or missing extension) is actually a directory.","commonSituations":"Agent builds a path by forgetting the filename ('notes/' vs 'notes/todo.md'); user data contains a directory where a file was expected (e.g. a directory named 'README.md'); glob/list results truncated so the file portion of the path was dropped.","solutions":["Append the actual filename to the path before reading.","Call stat/list on the path first and branch: if type is 'directory', list it or read a specific child instead.","Catch IsDirectoryError and fall back to listing the directory contents.","Verify the path exists as a file with fs.stat before calling readFile."],"exampleFix":"// before\nconst txt = await fs.readFile('docs'); // IsDirectoryError\n// after\nconst entries = await fs.list('docs');\nconst txt = await fs.readFile('docs/index.md');","handlingStrategy":"validation","validationCode":"const s = await ws.stat(p);\nif (s.type === 'directory') {\n  // list it or read a specific child instead of readFile\n}\nawait ws.readFile(p);","typeGuard":"import { IsDirectoryError } from '@mastra/core/workspace/errors';\nfunction isDirectoryError(e: unknown): e is IsDirectoryError {\n  return e instanceof IsDirectoryError ||\n    (e instanceof Error && 'code' in e && (e as { code?: string }).code === 'EISDIR');\n}","tryCatchPattern":"try {\n  return await ws.readFile(p, { encoding: 'utf8' });\n} catch (e) {\n  if (isDirectoryError(e)) {\n    return await ws.list(e.path).then(entries => entries.map(x => x.name));\n  }\n  throw e;\n}","preventionTips":["Branch on FileStat.type from stat/list results before reading.","Never build read paths from directory listings without taking entry.name.","Require an explicit filename in user/model supplied paths.","When a path may be either, stat first — it's one call and avoids the error entirely."],"tags":["filesystem","eisdir","wrong-path-type"],"backgroundTag":"eisdir-read-directory","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}