{"record":{"id":"9c4358e1e499e358","repo":"mastra-ai/mastra","slug":"read-only-9c4358","errorCode":"READ_ONLY","errorMessage":"Workspace is in read-only mode. Cannot perform: write_file","messagePattern":"Workspace is in read-only mode\\. Cannot perform: write_file","errorType":"error_code","errorClass":"WorkspaceReadOnlyError","httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/tools/write-file.ts","lineNumber":30,"sourceCode":"  inputSchema: z.object({\n    path: z.string().describe('The path where to write the file (e.g., \"data/output.txt\")'),\n    content: z.string().describe('The content to write to the file'),\n    overwrite: z.boolean().optional().default(true).describe('Whether to overwrite the file if it already exists'),\n  }),\n  execute: async ({ path, content, overwrite }, context) => {\n    const { workspace, filesystem } = requireFilesystem(context);\n    await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE);\n\n    const span = startWorkspaceSpan(context, workspace, {\n      category: 'filesystem',\n      operation: 'writeFile',\n      input: { path, overwrite, contentLength: content.length },\n      attributes: { filesystemProvider: filesystem.provider },\n    });\n\n    try {\n      if (filesystem.readOnly) {\n        throw new WorkspaceReadOnlyError('write_file');\n      }\n\n      await filesystem.writeFile(path, content, {\n        overwrite,\n        expectedMtime: (context as any)?.__expectedMtime,\n      });\n\n      const size = Buffer.byteLength(content, 'utf-8');\n      let output = `Wrote ${size} bytes to ${path}`;\n      output += await getEditDiagnosticsText(workspace, path, content);\n      span.end({ success: true }, { bytesTransferred: size });\n      return output;\n    } catch (err) {\n      span.error(err);\n      throw err;\n    }\n  },\n});","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/tools/write-file.ts#L12-L48","documentation":"The `writeFile` tool refuses to write when the workspace filesystem is read-only. Before calling `filesystem.writeFile`, it checks `filesystem.readOnly` and throws `WorkspaceReadOnlyError('write_file')`. This protects read-only mounted workspaces from any mutation via agent tools.","triggerScenarios":"Calling the `write_file` workspace tool while `filesystem.readOnly === true`, including with `overwrite: true` — the check happens before any write attempt.","commonSituations":"Agents attached to a read-only snapshot or prod mount; the `expectedMtime` concurrency mechanism irrelevant because writes are disallowed entirely; forgetting to disable write tools on read-only workspaces.","solutions":["Construct the filesystem with read-only disabled if writes are intended","Remove write_file (and other mutators) from the tools config for read-only workspaces","Persist intended changes elsewhere (e.g. output a patch) and apply them outside the read-only workspace"],"exampleFix":"// before\nnew LocalFilesystem('/mnt/readonly', { readOnly: true }) // write_file tool enabled\n\n// after\nnew LocalFilesystem('/mnt/readonly', { readOnly: true })\n// tools: only read tools enabled for this workspace","handlingStrategy":"validation","validationCode":"if (filesystem.readOnly) {\n  throw new Error('write_file cannot be used on a read-only workspace.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await writeFileTool.execute({ path, content }, ctx);\n} catch (err) {\n  if (err?.code === 'READ_ONLY') {\n    return { error: 'Workspace is read-only; produce a diff/patch instead.' };\n  }\n  throw err;\n}","preventionTips":["Exclude write_file and other mutators from tools config whenever readOnly is true","State read-only constraints in the agent system prompt","Test workspace setups: assert no write tools registered for readOnly filesystems"],"tags":["read-only","filesystem","write","workspace-tools"],"backgroundTag":"read-only-filesystem","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}