google-gemini/gemini-cli · error · Error

ENOENT

ENOENT

Error message

Sandbox Error: read_file failed for '${filePath}'. Exit code ${code}. ${error ? 'Details: ' + error : ''}

What it means

ENOENT 'Sandbox Error: read_file failed for X' is thrown by SandboxedFileSystemService.readTextFile when the sandboxed __read child process exits non-zero AND its stderr matches an ENOENT-like phrase. The wrapper attaches code:'ENOENT' so callers can distinguish missing-file from permission/spawn failures.

Source

Thrown at packages/core/src/services/sandboxedFileSystemService.ts:95

        child.stderr?.on('data', (data) => {
          error += data.toString();
        });

        child.on('close', (code) => {
          if (code === 0) {
            resolve(output);
          } else {
            const isEnoent =
              error.toLowerCase().includes('no such file or directory') ||
              error.toLowerCase().includes('enoent') ||
              error.toLowerCase().includes('could not find file') ||
              error.toLowerCase().includes('could not find a part of the path');
            const err = new Error(
              `Sandbox Error: read_file failed for '${filePath}'. Exit code ${code}. ${error ? 'Details: ' + error : ''}`,
            );
            if (isEnoent) {
              Object.assign(err, { code: 'ENOENT' });
            }
            reject(err);
          }
        });

        child.on('error', (err) => {
          reject(
            new Error(
              `Sandbox Error: Failed to spawn read_file for '${filePath}': ${err.message}`,
            ),
          );
        });
      });
    } finally {
      prepared.cleanup?.();
    }
  }

View on GitHub (pinned to 5024443c72)

Solutions

  1. Existence-check before read (config.getFileSystemService().readTextFile inside an ENOENT catch, or fs.stat).
  2. Verify the path is inside the sandbox cwd and allowedPaths — sandbox path remapping can resolve to a different root.
  3. If the file should exist, re-run the tool that was supposed to create it.

Example fix

// before
const txt = await fs.readTextFile(p);
// after
try { const txt = await fs.readTextFile(p); }
catch (e) { if (isNodeError(e) && e.code === 'ENOENT') { /* create or skip */ } else throw e; }
Defensive patterns

Strategy: try-catch

Validate before calling

// existence-check via the same FS service to respect sandbox mapping
const exists = await config.getFileSystemService().exists(filePath);
if (!exists) return { fileExists: false };

Type guard

function isSandboxEnoent(e: unknown): boolean {
  return isNodeError(e) && (e as NodeJS.ErrnoException).code === 'ENOENT';
}

Try / catch

try { return await fs.readTextFile(p); }
catch (e) {
  if (isSandboxEnoent(e)) { /* treat as new file */ return ''; }
  throw e;
}

Prevention

When it happens

Trigger: readTextFile(filePath) -> sanitizeAndValidatePath OK -> spawn __read -> child exits non-zero -> stderr contains 'no such file or directory' | 'enoent' | 'could not find file' | 'could not find a part of the path' -> reject(err with code ENOENT).

Common situations: write-file/edit tool targets a file the model assumed existed; path was mapped to a sandbox root that does not contain the file; file was deleted between the tool listing and the read; Windows sandbox reporting 'could not find a part of the path'.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/33c7822d77cd04b1. Report an issue: GitHub.