{"record":{"id":"e0707d241c6cfe38","repo":"mastra-ai/mastra","slug":"eacces","errorCode":"EACCES","errorMessage":"Permission denied: ${operation} (filesystem is read-only) on ${path}","messagePattern":"Permission denied: (.+?) \\(filesystem is read-only\\) on (.+?)","errorType":"exception","errorClass":"PermissionError","httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/filesystem/composite-filesystem.ts","lineNumber":264,"sourceCode":"    return entriesMap.size > 0 ? Array.from(entriesMap.values()) : null;\n  }\n\n  private isVirtualPath(path: string): boolean {\n    const normalized = this.normalizePath(path);\n    if (normalized === '/' && !this._mounts.has('/')) return true;\n    for (const mountPath of this._mounts.keys()) {\n      if (mountPath.startsWith(normalized + '/')) return true;\n    }\n    return false;\n  }\n\n  /**\n   * Assert that a filesystem is writable (not read-only).\n   * @throws {PermissionError} if the filesystem is read-only\n   */\n  private assertWritable(fs: WorkspaceFilesystem, path: string, operation: string): void {\n    if (fs.readOnly) {\n      throw new PermissionError(path, `${operation} (filesystem is read-only)`);\n    }\n  }\n\n  // ===========================================================================\n  // WorkspaceFilesystem Implementation\n  // ===========================================================================\n\n  async init(): Promise<void> {\n    this.status = 'initializing';\n    for (const [mountPath, fs] of this._mounts.entries()) {\n      try {\n        await callLifecycle(fs, 'init');\n      } catch (e) {\n        // Individual mount failed - it will have status='error'\n        // Log but continue with other mounts\n        const message = e instanceof Error ? e.message : String(e);\n        console.warn(`[CompositeFilesystem] Mount \"${mountPath}\" failed to initialize: ${message}`);\n      }","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/filesystem/composite-filesystem.ts#L246-L282","documentation":"A PermissionError (code EACCES) thrown by assertWritable when a write-style operation targets a mount whose filesystem is read-only. CompositeFilesystem derives its own readOnly flag from whether all mounts are read-only, and write methods (writeFile, appendFile, deleteFile, copyFile, moveFile, mkdir) check the resolved mount before delegating. This protects backends mounted intentionally as immutable (e.g., read-only templates or shared assets).","triggerScenarios":"Calling writeFile/appendFile/deleteFile/copyFile/moveFile/mkdir with a path that resolves to a mount constructed with readOnly: true (or whose underlying fs reports readOnly).","commonSituations":"Mounting a directory as read-only for reference but application code assumes it's writable; env/config marking production asset mounts read-only; writing generated output into a templates mount instead of a writable data mount.","solutions":["Write to a different mount path that resolves to a writable filesystem.","If the mount should be writable, remove readOnly from its constructor config.","Check fs.readOnly on the resolved mount in app code before attempting writes.","Route generated/user content to a dedicated writable mount (e.g., '/data') and keep read-only assets separate."],"exampleFix":"// before\nnew CompositeFilesystem({ mounts: { '/assets': new LocalFilesystem('/srv/assets', { readOnly: true }), '/': rwFs } });\nawait fs.writeFile('/assets/out.txt', 'x'); // EACCES\n// after\nawait fs.writeFile('/out.txt', 'x'); // writes via writable '/' mount","handlingStrategy":"try-catch","validationCode":"// resolve the same way the composite does, or expose fs.readOnly\nconst mount = mounts[normalizePrefix(path)];\nif (mount?.readOnly) throw new Error(`Refusing write to read-only mount at ${path}`);","typeGuard":"function isWritable(fs: WorkspaceFilesystem): boolean { return !fs.readOnly; }","tryCatchPattern":"try { await composite.writeFile(path, data); } catch (e) { if ((e as any).code === 'EACCES' || /read-only/.test((e as Error).message)) { await composite.writeFile(fallbackWritablePath(path), data); } else throw e; }","preventionTips":["Keep read-only mounts for assets only; route generated content to writable mounts.","Check fs.readOnly before performing any write-style operation.","Document mount writability in workspace configuration."],"tags":["workspace","filesystem","permissions","read-only"],"backgroundTag":"read-only-filesystem","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}