mastra-ai/mastra · error
readFile ${path} failed (exit ${result.exitCode}): ${result.
Error message
readFile ${path} failed (exit ${result.exitCode}): ${result.stderr.trim()} What it means
When the sandbox readFile probe command exits with a non-zero code that is neither EXIT_IS_DIRECTORY nor EXIT_NOT_FOUND, readFile throws this generic Error including the path, exit code, and the shell's stderr. It means the read genuinely failed at the shell level — e.g. permission denial or the base64 utility failing — rather than a missing file or a directory target.
Source
Thrown at mastracode/sdk/src/agents/sandbox-filesystem.ts:258
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()}`);
}
const buffer = Buffer.from(result.stdout.replace(/\s/g, ''), 'base64');
if (options?.encoding) {
return buffer.toString(options.encoding);
}
return buffer;
}
async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void> {
const abs = await this.resolveAsync(path);
await this.assertContainedDest(abs, path);
const b64 = toBuffer(content).toString('base64');
const dir = posixPath.dirname(abs);
const mkdir = options?.recursive === false ? '' : `mkdir -p ${shellQuote(dir)} && `;
if (options?.overwrite === false) {
// `set -C` (noclobber) makes the redirect itself the exclusivity check —
// no exists() pre-check that could race with a concurrent writer.
const result = await this.exec(View on GitHub (pinned to 75dd419e61)
Solutions
- Read the stderr in the message to identify the shell-level cause (permission denied vs command not found).
- Fix file permissions in the sandbox (chmod u+r) or run the step as a user with read access.
- Ensure the file is not being deleted/rotated concurrently between the existence probe and the read.
- Confirm the sandbox image provides base64 (coreutils or busybox applet) — otherwise use a different read mechanism.
- If only the existence/permission classification is needed, guard with a stat/list operation instead of reading full contents.
Example fix
// before\nconst data = await fs.readFile('secrets/key.pem');\n// after\ntry {\n const data = await fs.readFile('secrets/key.pem');\n} catch (e) {\n if (e instanceof Error && e.message.includes('Permission denied')) {\n await fs.exec('chmod u+r secrets/key.pem || true');\n }\n throw e;\n} Defensive patterns
Strategy: retry
Validate before calling
const ls = await fs.readDirectory(dirPath); // confirm file is listed and readable\nclassifyPaths(ls);
Type guard
function isReadFailureError(e: unknown): boolean {\n return e instanceof Error && /^readFile .* failed \\(exit/.test(e.message);\n} Try / catch
try {\n const data = await fs.readFile(path);\n} catch (e) {\n if (e instanceof Error && e.message.includes('failed (exit')) {\n // inspect e.message for stderr, optionally retry once after chmod/wait\n }\n throw e;\n} Prevention
- Keep files world-readable inside the sandbox (mind umask/chmod).
- Don't delete or rotate files concurrently with reads.
- Confirm the sandbox image ships base64/coreutils.
- Read stderr from the thrown message before retrying blindly.
When it happens
Trigger: readFile on a file the sandbox user lacks permission to read (base64 < file fails with EACCES); a file that exists at probe time but disappears before the redirect; a restricted/base64-less shell environment; I/O errors on the sandbox filesystem.
Common situations: Files created with restrictive modes (chmod 000 or umask issues) by a previous step; read-protected mount points inside the workdir; sandbox images where PATH or busybox applets differ so stderr reveals the real command failure.
Related errors
- Unable to verify path stays within workspace root: ${inputPa
- ${context} failed (exit ${result.exitCode}): ${result.stderr
- 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/2479b7f07749c6af.
Report an issue: GitHub.