mastra-ai/mastra · error

Failed to copy studio assets from "${studioSource}" to "${st

Error message

Failed to copy studio assets from "${studioSource}" to "${staticDir}": ${err instanceof Error ? err.message : err}

What it means

The Vercel deployer's prepare() copies prebuilt studio static assets into the Vercel output static directory (.vercel/output/static). If the copy operation fails for any reason (missing source, permissions, disk error), it wraps the underlying error in this descriptive message so you know which step of deployment failed.

Source

Thrown at deployers/vercel/src/index.ts:63

    await super.prepare(outputDirectory);

    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);

    const studioSource = join(dirname(__dirname), 'dist', 'studio');

    this.writeVercelJSON(
      join(outputDirectory, this.outputDir, '..', '..'),
      this.studio ? this.readStudioRouteRoots(studioSource) : [],
    );

    if (this.studio) {
      const staticDir = join(outputDirectory, '.vercel', 'output', 'static');

      try {
        await copy(studioSource, staticDir, { overwrite: true });
      } catch (err) {
        throw new Error(
          `Failed to copy studio assets from "${studioSource}" to "${staticDir}": ${err instanceof Error ? err.message : err}`,
        );
      }

      this.injectStudioConfig(staticDir);
    }
  }

  /**
   * Studio's top-level route segments, emitted by the Studio build alongside index.html.
   * The Vercel route table needs them explicitly: custom `registerApiRoute()` paths are mounted
   * at the root of the server, so the function has to own every path Studio doesn't claim.
   */
  private readStudioRouteRoots(studioSource: string): string[] {
    const manifestPath = join(studioSource, 'routes-manifest.json');

    try {
      const roots = JSON.parse(readFileSync(manifestPath, 'utf-8'));

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Build the studio so studioSource exists before running the Vercel deployer.
  2. Check the inner error (the message includes err.message) and fix the root cause (permissions, disk space).
  3. Ensure .vercel/output/static is writable and not locked by another process.
  4. Verify the outputDirectory option points to the correct build directory.

Example fix

// before
npx vercel deploy  # studio never built
// after
pnpm build:studio && npx vercel deploy
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
if (!existsSync(studioSource)) {
  throw new Error(`Studio assets not built: ${studioSource} missing. Run the studio build first.`);
}

Type guard

function isNodeError(err: unknown): err is Error {
  return err instanceof Error;
}

Try / catch

try {
  await deployer.prepare();
} catch (err) {
  if (String((err as Error).message).startsWith('Failed to copy studio assets')) {
    console.error('Studio build missing or copy failed:', (err as Error).message);
    // rebuild studio then retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Deploying with this.studio enabled while studioSource does not exist (studio not built first), or copy() failing due to permissions, ENOSPC, or EBUSY on .vercel/output/static.

Common situations: Forgetting to run the studio build before deploying; deploying from a container/user without write access to the output directory; stale file locks in CI.

Related errors


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