{"record":{"id":"68bc1eb07cc14b46","repo":"mastra-ai/mastra","slug":"movefile-src-dest-failed-exit-result-e","errorCode":null,"errorMessage":"moveFile ${src} -> ${dest} failed (exit ${result.exitCode}): ${result.stderr.trim()}","messagePattern":"moveFile (.+?) -> (.+?) failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/agents/sandbox-filesystem.ts","lineNumber":384,"sourceCode":"    await this.assertContainedDest(destAbs, dest);\n    if (options?.overwrite === false) {\n      // `mv -n` exits 0 even when it skips, so detect a skipped move by the\n      // source surviving. The no-clobber rename itself is atomic; no racy\n      // exists() pre-check.\n      const result = await this.exec(\n        [\n          `src=${shellQuote(srcAbs)}`,\n          `dest=${shellQuote(destAbs)}`,\n          `if [ ! -e \"$src\" ] && [ ! -L \"$src\" ]; then exit ${EXIT_NOT_FOUND}; fi`,\n          `mkdir -p ${shellQuote(posixPath.dirname(destAbs))} || exit 1`,\n          `mv -n \"$src\" \"$dest\" 2>/dev/null || exit 1`,\n          `if [ -e \"$src\" ] || [ -L \"$src\" ]; then exit ${EXIT_EXISTS}; fi`,\n        ].join('\\n'),\n      );\n      if (result.exitCode === EXIT_NOT_FOUND) throw new FileNotFoundError(src);\n      if (result.exitCode === EXIT_EXISTS) throw new FileExistsError(dest);\n      if (result.exitCode !== 0) {\n        throw new Error(`moveFile ${src} -> ${dest} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);\n      }\n      return;\n    }\n    const result = await this.exec(\n      `if [ ! -e ${shellQuote(srcAbs)} ]; then exit ${EXIT_NOT_FOUND}; fi; mkdir -p ${shellQuote(posixPath.dirname(destAbs))} && mv ${shellQuote(srcAbs)} ${shellQuote(destAbs)}`,\n    );\n    if (result.exitCode === EXIT_NOT_FOUND) throw new FileNotFoundError(src);\n    if (result.exitCode !== 0) {\n      throw new Error(`moveFile ${src} -> ${dest} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);\n    }\n  }\n\n  // ── Directory operations ───────────────────────────────────────────────\n\n  async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> {\n    const abs = await this.resolveAsync(path);\n    await this.assertContainedDest(abs, path);\n    const flag = options?.recursive === false ? '' : '-p ';","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/agents/sandbox-filesystem.ts#L366-L402","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — dest parent is not writable by the sandbox user\nawait sandbox.fs.moveFile('/app/tmp.txt', '/root/tmp.txt');\n\n// after — move within a writable directory\nawait sandbox.fs.moveFile('/app/tmp.txt', '/app/data/tmp.txt');","handlingStrategy":"try-catch","validationCode":"// validate src exists and dest is not inside a non-directory path\nawait sandbox.fs.stat(src);\nawait sandbox.fs.mkdir(posixPath.dirname(dest), { recursive: true });\nif (await sandbox.fs.exists(dest)) {\n  throw new Error(`dest already exists: ${dest}`);\n}","typeGuard":"function isFileExistsOrNotFound(e: unknown): boolean {\n  return e instanceof FileExistsError || e instanceof FileNotFoundError;\n}","tryCatchPattern":"try {\n  await sandbox.fs.moveFile(src, dest, { noOverwrite: true });\n} catch (e) {\n  if (isFileExistsOrNotFound(e)) {\n    // handled typed outcomes (dest taken / src missing)\n    return;\n  }\n  throw e; // unexpected exit code; message carries sandbox stderr\n}","preventionTips":["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."],"tags":["sandbox","filesystem","shell-command","move"],"backgroundTag":"sandbox-command-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}