mastra-ai/mastra · error · WorkspaceReadOnlyError

READ_ONLY

READ_ONLY

Error message

Workspace is in read-only mode. Cannot perform: ast_edit

What it means

Thrown by the ast_edit workspace tool when the workspace filesystem is in read-only mode. AST-based code transformations mutate files, so they are blocked before loading ast-grep. The error carries code READ_ONLY via WorkspaceReadOnlyError with the offending operation name.

Source

Thrown at packages/core/src/workspace/tools/ast-edit.ts:448

        isDefault: z.boolean().optional().describe('Whether the first name is a default import'),
      })
      .optional()
      .describe('Required for add-import transform. Specifies the module and names to import.'),
  }),
  execute: async ({ path, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
    const { workspace, filesystem } = requireFilesystem(context);
    await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT);

    const span = startWorkspaceSpan(context, workspace, {
      category: 'filesystem',
      operation: 'astEdit',
      input: { path, transform, pattern },
      attributes: { filesystemProvider: filesystem.provider },
    });

    try {
      if (filesystem.readOnly) {
        throw new WorkspaceReadOnlyError('ast_edit');
      }

      // Load ast-grep (cached after first call)
      const astGrep = await loadAstGrep();
      if (!astGrep) {
        span.end({ success: false });
        return '@ast-grep/napi is not available. Install it to use AST editing.';
      }
      const { parse, Lang } = astGrep;

      // Read current content
      let content: string | Buffer;
      try {
        content = await filesystem.readFile(path, { encoding: 'utf-8' });
      } catch (error) {
        if (error instanceof FileNotFoundError) {
          span.end({ success: false });
          return `File not found: ${path}. Use the write file tool to create it first.`;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Configure the workspace filesystem as writable (remove readOnly / supply a writable provider)
  2. Mount or point the workspace at a writable copy of the files instead of a read-only source
  3. Skip ast_edit in read-only deployments and surface file changes through a separate write workflow
  4. Check workspace.filesystem read-only status before invoking edit tools to fail gracefully

Example fix

// before
new Workspace({ filesystem: createFilesystem({ root, readOnly: true }) });
// after
new Workspace({ filesystem: createFilesystem({ root, readOnly: false }) });
Defensive patterns

Strategy: validation

Validate before calling

if (workspace.filesystem && workspace.filesystem.readOnly) {
  throw new Error('ast_edit unavailable: workspace is read-only');
}

Type guard

function canEdit(fs: WorkspaceFilesystem | undefined): fs is WorkspaceFilesystem & { readOnly: false } {
  return !!fs && fs.readOnly === false;
}

Try / catch

try {
  await astEditTool.execute({ context: { path, transform, pattern }, ... });
} catch (e: any) {
  if (e?.code === 'READ_ONLY' || /read-only mode/i.test(e?.message ?? '')) {
    return { skipped: true, reason: 'workspace is read-only' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Invoking the ast_edit tool (with path, transform, pattern inputs) on a workspace whose filesystem provider was configured read-only, or whose readOnly flag is true at execution time.

Common situations: Running agents against a read-only workspace/deployment (e.g. production inspection, sandboxed preview); forgetting to enable write access for an editing agent.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1815df627e3c283f. Report an issue: GitHub.