{"record":{"id":"36ef7aa33887ecaa","repo":"mastra-ai/mastra","slug":"context-failed-exit-result-exitcode-res","errorCode":null,"errorMessage":"${context} failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}","messagePattern":"(.+?) failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/agents/sandbox-filesystem.ts","lineNumber":240,"sourceCode":"   * we check its realpath; for a not-yet-existing target we check the realpath\n   * of its nearest existing ancestor directory, since a symlinked parent is the\n   * escape vector (e.g. `link -> /etc` then writing `link/passwd`).\n   */\n  private async assertContainedDest(abs: string, inputPath: string): Promise<void> {\n    // First check the target itself (covers overwriting an existing symlink).\n    await this.assertContainedRealpath(abs, inputPath);\n    // Then check the parent directory's realpath; readlink -f resolves the\n    // nearest existing ancestor when the leaf doesn't exist yet.\n    const parent = posixPath.dirname(abs);\n    if (parent && parent !== abs) {\n      await this.assertContainedRealpath(parent, inputPath);\n    }\n  }\n\n  private async execOk(script: string, context: string): Promise<SandboxCommandResult> {\n    const result = await this.exec(script);\n    if (result.exitCode !== 0) {\n      throw new Error(`${context} failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}`);\n    }\n    return result;\n  }\n\n  // ── File operations ────────────────────────────────────────────────────\n\n  async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {\n    const abs = await this.resolveAsync(path);\n    await this.assertContainedRealpath(abs, path);\n    // Guard clauses first: redirecting from a directory \"succeeds\" with empty\n    // output on some shells, so classify before reading.\n    const result = await this.exec(\n      `if [ -d ${shellQuote(abs)} ]; then exit ${EXIT_IS_DIRECTORY}; elif [ ! -e ${shellQuote(abs)} ]; then exit ${EXIT_NOT_FOUND}; fi; base64 < ${shellQuote(abs)}`,\n    );\n    if (result.exitCode === EXIT_IS_DIRECTORY) throw new IsDirectoryError(path);\n    if (result.exitCode === EXIT_NOT_FOUND) throw new FileNotFoundError(path);\n    if (result.exitCode !== 0) {\n      throw new Error(`readFile ${path} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/agents/sandbox-filesystem.ts#L222-L258","documentation":"This is the sandbox's generic wrapper for any shell command it runs (writes, appends, deletes, mkdir, rmdir, init) that exits non-zero. It surfaces the exit code plus whatever the shell reported on stderr (or stdout) so the underlying sandbox failure is visible. It is not a distinct error class — the `context` prefix identifies which operation failed.","triggerScenarios":"Any of writeFile, appendFile, deleteFile, mkdir, rmdir, or init executes a composed shell script in the sandbox that returns a non-zero exit code — e.g. `mkdir -p` hitting a read-only volume, `rm` failing on a protected path, or the init script failing because the workdir is unavailable.","commonSituations":"Read-only or full filesystem in the sandbox/container; missing shell utilities in minimal images; sandbox session expired or not started before file operations; permissions/ownership mismatches on mounted volumes; writing into a path whose parent is a file rather than a directory.","solutions":["Read the `context` prefix and the captured stderr in the message to identify the failing operation and shell error","Verify the sandbox session/workdir is initialized and writable (run init or a probe write)","Fix the environment: free disk space, correct volume permissions, or install missing shell utilities in the sandbox image","Adjust the target path (e.g. ensure parent directories exist, or remove the file before recreating it)"],"exampleFix":"// before\nawait fs.writeFile('missing-dir/file.txt', 'hi'); // shell write fails, exit != 0\n// after\nawait fs.mkdir('missing-dir');\nawait fs.writeFile('missing-dir/file.txt', 'hi');","handlingStrategy":"try-catch","validationCode":"// Check the parent directory exists and the sandbox is writable before writing\nconst parent = targetPath.replace(/\\/[^/]+$/, '');\nawait fs.mkdir(parent); // mkdir itself reports a clear context if it fails\nconst probe = await fs.writeFile(`${parent}/.probe`, '');\nawait fs.deleteFile(`${parent}/.probe`);","typeGuard":null,"tryCatchPattern":"try {\n  await fs.writeFile(path, data);\n} catch (err) {\n  if (err instanceof Error && / failed \\(exit \\d+\\):/.test(err.message)) {\n    const context = err.message.split(' failed ')[0];\n    const detail = err.message.slice(err.message.indexOf(': ') + 2);\n    console.error(`Sandbox op '${context}' failed: ${detail}`); // retry once on transient errors\n  } else {\n    throw err;\n  }\n}","preventionTips":["Parse the `context` prefix and embedded stderr instead of treating the message as opaque","Ensure the sandbox session is initialized (init) before any file operations","Keep the sandbox image minimal but complete (coreutils, sh) and the volume writable with free space","Pre-create parent directories with mkdir rather than relying on implicit creation"],"tags":["sandbox","shell","exec","exit-code","filesystem"],"backgroundTag":"shell-command-nonzero-exit","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}