{"record":{"id":"8c5b9319e8af5d16","repo":"vercel/ai","slug":"file-not-found-inputpath","errorCode":null,"errorMessage":"File not found: ${inputPath}","messagePattern":"File not found: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/harness-cline/src/cline-remote-ops.ts","lineNumber":203,"sourceCode":"    }\n\n    const resolvedPath = lastOutputLine(result.output);\n    if (!resolvedPath) {\n      throw new Error(`Unable to resolve path: ${inputPath}`);\n    }\n    return assertWorkspacePath(resolvedPath);\n  };\n\n  const readFile = async (inputPath: string): Promise<string> => {\n    const remotePath = resolvePath(inputPath);\n    const resolved = await resolveReadableSandboxPath({\n      remotePath,\n      inputPath,\n      missingMessage: `File not found: ${inputPath}`,\n    });\n    const content = await sandbox.readTextFile({ path: resolved });\n    if (content == null) {\n      throw new Error(`File not found: ${inputPath}`);\n    }\n    return content;\n  };\n\n  const writeFile = async (\n    inputPath: string,\n    content: string,\n  ): Promise<void> => {\n    const remotePath = resolvePath(inputPath);\n    const resolved = await resolveWritableSandboxPath({\n      remotePath,\n      inputPath,\n    });\n    // `writeTextFile` creates parent directories recursively per the\n    // SandboxSession contract, so no explicit mkdir is needed.\n    await sandbox.writeTextFile({ path: resolved, content });\n  };\n","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-cline/src/cline-remote-ops.ts#L185-L221","documentation":"Thrown by readFile when the path resolved and passed the existence check, but the sandbox's readTextFile returned null/undefined — meaning the file could not actually be read as text (e.g. it is a directory, a binary file, or was removed between the check and the read). The library reports it as 'File not found' with the caller's original input path.","triggerScenarios":"readFile('notes/') where the path points at a directory; readFile on a binary file that readTextFile refuses to decode; a race where the file is deleted between resolveReadableSandboxPath and readTextFile; a sandbox that returns null for unreadable/permission-denied files.","commonSituations":"Model-driven tool calls reading directories as if they were files; reading binary artifacts (images, compiled output) that only support text reads; TOCTOU races in active sandboxes; permissions restricted inside the sandbox container.","solutions":["Check that the path targets a regular file, not a directory (use ops.ls or ops.bash with `test -f`).","For binary content, do not use readFile — copy or inspect the file via ops.bash commands instead.","Retry the read once if the file was concurrently modified; otherwise re-list the directory to find the correct file name.","Verify sandbox file permissions allow the session user to read the file."],"exampleFix":"// before: reading a directory\nconst content = await ops.readFile('src'); // File not found: src\n\n// after: only read regular files\nconst entries = await ops.ls('src');\nconst content = await ops.readFile(`src/${entries[0]}`);","handlingStrategy":"try-catch","validationCode":"async function isRegularTextFile(ops, p) {\n  const r = await ops.bash(`test -f ${JSON.stringify(p)} && echo file || echo notfile`);\n  return r.output.includes('file');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await ops.readFile(path);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('File not found:')) {\n    const parent = path.posix.dirname(path);\n    const entries = await ops.ls(parent); // discover the real name\n    return ops.readFile(`${parent}/${entries.find(x => x === path.posix.basename(path)) ?? entries[0]}`);\n  }\n  throw e;\n}","preventionTips":["Never pass directory paths to readFile — check with `test -f` when unsure.","Treat readFile as text-only; use bash commands for binary content.","Re-list the directory when a path fails; names may have changed.","Verify sandbox permissions allow the session user to read target files."],"tags":["filesystem","file-not-found","sandbox"],"backgroundTag":"file-not-found","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}