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

  1. Inspect the stderr included in the message for the precise shell error.
  2. Confirm the dest parent directory exists as a directory and is writable.
  3. If src and dest are on different sandbox mounts, copy then delete instead of a single mv.
  4. Fix permissions with chmod/chown inside the sandbox or recreate the sandbox.
  5. 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

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


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