{"record":{"id":"2479b7f07749c6af","repo":"mastra-ai/mastra","slug":"readfile-path-failed-exit-result-exitcode","errorCode":null,"errorMessage":"readFile ${path} failed (exit ${result.exitCode}): ${result.stderr.trim()}","messagePattern":"readFile (.+?) failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/agents/sandbox-filesystem.ts","lineNumber":258,"sourceCode":"      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()}`);\n    }\n    const buffer = Buffer.from(result.stdout.replace(/\\s/g, ''), 'base64');\n    if (options?.encoding) {\n      return buffer.toString(options.encoding);\n    }\n    return buffer;\n  }\n\n  async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void> {\n    const abs = await this.resolveAsync(path);\n    await this.assertContainedDest(abs, path);\n    const b64 = toBuffer(content).toString('base64');\n    const dir = posixPath.dirname(abs);\n    const mkdir = options?.recursive === false ? '' : `mkdir -p ${shellQuote(dir)} && `;\n    if (options?.overwrite === false) {\n      // `set -C` (noclobber) makes the redirect itself the exclusivity check —\n      // no exists() pre-check that could race with a concurrent writer.\n      const result = await this.exec(","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/agents/sandbox-filesystem.ts#L240-L276","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// 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}","handlingStrategy":"retry","validationCode":"const ls = await fs.readDirectory(dirPath); // confirm file is listed and readable\\nclassifyPaths(ls);","typeGuard":"function isReadFailureError(e: unknown): boolean {\\n  return e instanceof Error && /^readFile .* failed \\\\(exit/.test(e.message);\\n}","tryCatchPattern":"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}","preventionTips":["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."],"tags":["filesystem","sandbox","permissions","shell"],"backgroundTag":"command-exit-code-failure","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}