mastra-ai/mastra · error
${context} failed (exit ${result.exitCode}): ${result.stderr
Error message
${context} failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()} What it means
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.
Source
Thrown at mastracode/sdk/src/agents/sandbox-filesystem.ts:240
* we check its realpath; for a not-yet-existing target we check the realpath
* of its nearest existing ancestor directory, since a symlinked parent is the
* escape vector (e.g. `link -> /etc` then writing `link/passwd`).
*/
private async assertContainedDest(abs: string, inputPath: string): Promise<void> {
// First check the target itself (covers overwriting an existing symlink).
await this.assertContainedRealpath(abs, inputPath);
// Then check the parent directory's realpath; readlink -f resolves the
// nearest existing ancestor when the leaf doesn't exist yet.
const parent = posixPath.dirname(abs);
if (parent && parent !== abs) {
await this.assertContainedRealpath(parent, inputPath);
}
}
private async execOk(script: string, context: string): Promise<SandboxCommandResult> {
const result = await this.exec(script);
if (result.exitCode !== 0) {
throw new Error(`${context} failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}`);
}
return result;
}
// ── File operations ────────────────────────────────────────────────────
async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {
const abs = await this.resolveAsync(path);
await this.assertContainedRealpath(abs, path);
// Guard clauses first: redirecting from a directory "succeeds" with empty
// output on some shells, so classify before reading.
const result = await this.exec(
`if [ -d ${shellQuote(abs)} ]; then exit ${EXIT_IS_DIRECTORY}; elif [ ! -e ${shellQuote(abs)} ]; then exit ${EXIT_NOT_FOUND}; fi; base64 < ${shellQuote(abs)}`,
);
if (result.exitCode === EXIT_IS_DIRECTORY) throw new IsDirectoryError(path);
if (result.exitCode === EXIT_NOT_FOUND) throw new FileNotFoundError(path);
if (result.exitCode !== 0) {
throw new Error(`readFile ${path} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);View on GitHub (pinned to 75dd419e61)
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)
Example fix
// before
await fs.writeFile('missing-dir/file.txt', 'hi'); // shell write fails, exit != 0
// after
await fs.mkdir('missing-dir');
await fs.writeFile('missing-dir/file.txt', 'hi'); Defensive patterns
Strategy: try-catch
Validate before calling
// Check the parent directory exists and the sandbox is writable before writing
const parent = targetPath.replace(/\/[^/]+$/, '');
await fs.mkdir(parent); // mkdir itself reports a clear context if it fails
const probe = await fs.writeFile(`${parent}/.probe`, '');
await fs.deleteFile(`${parent}/.probe`); Try / catch
try {
await fs.writeFile(path, data);
} catch (err) {
if (err instanceof Error && / failed \(exit \d+\):/.test(err.message)) {
const context = err.message.split(' failed ')[0];
const detail = err.message.slice(err.message.indexOf(': ') + 2);
console.error(`Sandbox op '${context}' failed: ${detail}`); // retry once on transient errors
} else {
throw err;
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unable to verify path stays within workspace root: ${inputPa
- readFile ${path} failed (exit ${result.exitCode}): ${result.
- writeFile ${path} failed (exit ${result.exitCode}): ${result
- Directory not empty or not found: ${path}
- Invalid environment variable name: "${key}"
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/36ef7aa33887ecaa.
Report an issue: GitHub.