mastra-ai/mastra · error
Failed to copy studio assets from
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.
Solutions
- Build the studio so studioSource exists before running the Vercel deployer.
- Check the inner error (the message includes err.message) and fix the root cause (permissions, disk space).
- Ensure .vercel/output/static is writable and not locked by another process.
- 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
- Always build the studio before invoking the Vercel deployer.
- Add a build-order check in CI (studio build must precede deploy).
- Verify write permissions on .vercel/output/static.
- Read the inner err.message embedded in the error for the root cause.
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
- Failed to read studio routes manifest at
- Missing required file, checked the following paths
- DEPLOYER_BUNDLER_BUNDLE_STAGE_FAILED
- expected an array of route segments
- Failed to copy studio assets from
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4c75d83bff5cccb7.
Report an issue: GitHub.
Appendix: 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)