mastra-ai/mastra · error · WorkspaceReadOnlyError
READ_ONLY
READ_ONLY
Error message
Workspace is in read-only mode. Cannot perform: ${operation} What it means
LocalFilesystem throws WorkspaceReadOnlyError (code READ_ONLY) when any mutating filesystem operation is attempted while the provider was constructed with readOnly: true. It is raised in assertWritable(), which every write path (writeFile, appendFile, deleteFile, copyFile, moveFile, mkdir) calls before touching disk. The error guards a deliberate configuration choice, not a runtime fault, so no data was modified.
Source
Thrown at packages/core/src/workspace/filesystem/local-filesystem.ts:339
* Uses the same resolution logic as internal file operations.
* Returns `undefined` if the path violates containment.
*/
resolveAbsolutePath(inputPath: string): string | undefined {
try {
return this.resolvePath(inputPath);
} catch {
// PermissionError from containment check — path is not resolvable
return undefined;
}
}
private toRelativePath(absolutePath: string): string {
return nodePath.relative(this._basePath, absolutePath).replace(/\\/g, '/');
}
private assertWritable(operation: string): void {
if (this.readOnly) {
throw new WorkspaceReadOnlyError(operation);
}
}
/**
* Verify that the resolved path doesn't escape basePath via symlinks.
* Uses realpath to resolve symlinks and check the actual target.
*/
private async assertPathContained(absolutePath: string): Promise<void> {
if (!this._contained) return;
if (this._allowedPaths.some(root => this._isWithinRoot(absolutePath, root))) {
return;
}
// Resolve symlinks for the target path. If it doesn't exist,
// there are no symlinks to escape through — nothing to check.
let targetReal: string;
try {View on GitHub (pinned to 75dd419e61)
Solutions
- Remove readOnly: true from the LocalFilesystem options (or use a separate writable workspace) if writes are intended.
- Check workspace.filesystem.info / isReadOnly before issuing write calls and route writes to a writable provider.
- Catch WorkspaceReadOnlyError in the agent/tool layer and surface a clear message telling the model the workspace cannot be written.
- If only some mounts are read-only, target the write to a mounted filesystem that is writable.
Example fix
// before
const ws = new Workspace({ filesystem: new LocalFilesystem({ basePath: './data', readOnly: true }) });
await ws.writeFile('out.txt', 'hi'); // throws WorkspaceReadOnlyError
// after
const ws = new Workspace({ filesystem: new LocalFilesystem({ basePath: './data' }) });
await ws.writeFile('out.txt', 'hi'); Defensive patterns
Strategy: try-catch
Validate before calling
import { LocalFilesystem } from '@mastra/core/workspace';
if (fsProvider.info?.readOnly) {
throw new Error('Workspace filesystem is read-only; writes are not permitted');
} Type guard
import { WorkspaceReadOnlyError } from '@mastra/core/workspace/errors';
function isReadOnlyError(e: unknown): e is WorkspaceReadOnlyError {
return e instanceof WorkspaceReadOnlyError ||
(e instanceof Error && 'code' in e && (e as { code?: string }).code === 'READ_ONLY');
} Try / catch
try {
await ws.writeFile('out.txt', data);
} catch (e) {
if (isReadOnlyError(e)) {
logger.warn('Workspace is read-only; skipping write');
return;
}
throw e;
} Prevention
- Check the provider's readOnly flag at startup and configure write tools only for writable workspaces.
- Give agents a separate scratch workspace for writes and keep reference data read-only.
- Include readOnly status in tool descriptions so the model doesn't attempt writes.
- Centralize writes behind a helper that checks writability once instead of scattering raw calls.
When it happens
Trigger: Calling writeFile, appendFile, deleteFile, copyFile, moveFile, or mkdir on a LocalFilesystem created with { readOnly: true } (or a Workspace configured with a read-only filesystem/mount); agent tools that write to files when the workspace policy is read-only.
Common situations: Serving a workspace as read-only reference material (docs, skills) while an agent attempts to save output; forgetting readOnly was enabled after switching an environment to production-safe defaults; a mounted sub-filesystem is read-only while the caller expects writes to land there.
Related errors
- CompositeFilesystem requires at least one mount
- Nested mount paths are not supported: "${b}" is nested under
- EACCES
- READ_ONLY
- READ_ONLY
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/f4ca154a9d31e2b1.
Report an issue: GitHub.