mastra-ai/mastra · error
moveFile ${src} -> ${dest} failed (exit ${result.exitCode}):
Error message
moveFile ${src} -> ${dest} failed (exit ${result.exitCode}): ${result.stderr.trim()} What it means
This generic Error is raised by SandboxFilesystem.moveFile in its atomic/structured branch when the probe shell script (existence check on src, existence check on dest, then mv) exits with a code that is not the reserved EXIT_NOT_FOUND or EXIT_EXISTS sentinels. Those two codes are translated to FileNotFoundError and FileExistsError; every other non-zero exit (permission failure, mv crossing filesystem boundaries, sandbox degradation) becomes this error with the raw exit code and stderr attached.
Source
Thrown at mastracode/sdk/src/agents/sandbox-filesystem.ts:384
await this.assertContainedDest(destAbs, dest);
if (options?.overwrite === false) {
// `mv -n` exits 0 even when it skips, so detect a skipped move by the
// source surviving. The no-clobber rename itself is atomic; no racy
// exists() pre-check.
const result = await this.exec(
[
`src=${shellQuote(srcAbs)}`,
`dest=${shellQuote(destAbs)}`,
`if [ ! -e "$src" ] && [ ! -L "$src" ]; then exit ${EXIT_NOT_FOUND}; fi`,
`mkdir -p ${shellQuote(posixPath.dirname(destAbs))} || exit 1`,
`mv -n "$src" "$dest" 2>/dev/null || exit 1`,
`if [ -e "$src" ] || [ -L "$src" ]; then exit ${EXIT_EXISTS}; fi`,
].join('\n'),
);
if (result.exitCode === EXIT_NOT_FOUND) throw new FileNotFoundError(src);
if (result.exitCode === EXIT_EXISTS) throw new FileExistsError(dest);
if (result.exitCode !== 0) {
throw new Error(`moveFile ${src} -> ${dest} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);
}
return;
}
const result = await this.exec(
`if [ ! -e ${shellQuote(srcAbs)} ]; then exit ${EXIT_NOT_FOUND}; fi; mkdir -p ${shellQuote(posixPath.dirname(destAbs))} && mv ${shellQuote(srcAbs)} ${shellQuote(destAbs)}`,
);
if (result.exitCode === EXIT_NOT_FOUND) throw new FileNotFoundError(src);
if (result.exitCode !== 0) {
throw new Error(`moveFile ${src} -> ${dest} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);
}
}
// ── Directory operations ───────────────────────────────────────────────
async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> {
const abs = await this.resolveAsync(path);
await this.assertContainedDest(abs, path);
const flag = options?.recursive === false ? '' : '-p ';View on GitHub (pinned to 75dd419e61)
Solutions
- Inspect the stderr included in the message for the precise shell error.
- Confirm the dest parent directory exists as a directory and is writable.
- If src and dest are on different sandbox mounts, copy then delete instead of a single mv.
- Fix permissions with chmod/chown inside the sandbox or recreate the sandbox.
- Catch FileNotFoundError/FileExistsError separately so only unexpected failures reach this branch.
Example fix
// before — dest parent is not writable by the sandbox user
await sandbox.fs.moveFile('/app/tmp.txt', '/root/tmp.txt');
// after — move within a writable directory
await sandbox.fs.moveFile('/app/tmp.txt', '/app/data/tmp.txt'); Defensive patterns
Strategy: try-catch
Validate before calling
// validate src exists and dest is not inside a non-directory path
await sandbox.fs.stat(src);
await sandbox.fs.mkdir(posixPath.dirname(dest), { recursive: true });
if (await sandbox.fs.exists(dest)) {
throw new Error(`dest already exists: ${dest}`);
} Type guard
function isFileExistsOrNotFound(e: unknown): boolean {
return e instanceof FileExistsError || e instanceof FileNotFoundError;
} Try / catch
try {
await sandbox.fs.moveFile(src, dest, { noOverwrite: true });
} catch (e) {
if (isFileExistsOrNotFound(e)) {
// handled typed outcomes (dest taken / src missing)
return;
}
throw e; // unexpected exit code; message carries sandbox stderr
} Prevention
- Pre-create and permission-check the dest parent directory.
- Avoid moving files across different sandbox mounts with a single mv.
- Pre-check dest existence yourself when using noOverwrite so EXIT_EXISTS is the only dest conflict path.
- Recreate stale sandboxes after snapshot/restore operations to avoid permission drift.
When it happens
Trigger: Calling sandbox.files.moveFile(src, dest, options) where the multi-line probe-and-move script fails: the parent directory of dest cannot be created or written, the src cannot be read/renamed, or the shell itself fails partway through the joined script.
Common situations: Moving a file into a directory owned by another sandbox user; moving across mounts where mv must fall back to copy and fails; stale sandbox state after a snapshot restore; dest parent is actually a file, not a directory.
Related errors
- deleteFile ${path} failed (exit ${result.exitCode}): ${resul
- copyFile ${src} -> ${dest} failed (exit ${result.exitCode}):
- pull-failed
- Sandbox workspace root resolution returned an empty path
- Path escapes workspace root: ${inputPath}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/68bc1eb07cc14b46.
Report an issue: GitHub.