{"record":{"id":"5fbcca0f76cac160","repo":"jackwener/OpenCLI","slug":"file-read-error","errorCode":"FILE_READ_ERROR","errorMessage":"Unable to inspect file: ${resolvedPath}","messagePattern":"Unable to inspect file: (.+?)","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/paperreview/utils.js","lineNumber":67,"sourceCode":"export async function readPdfFile(inputPath) {\n    const rawPath = trimOrEmpty(inputPath);\n    if (!rawPath) {\n        throw new CliError('ARGUMENT', 'A PDF path is required.', 'Provide a local PDF file path');\n    }\n    const resolvedPath = path.resolve(rawPath);\n    const fileName = path.basename(resolvedPath);\n    if (!fileName.toLowerCase().endsWith('.pdf')) {\n        throw new CliError('ARGUMENT', 'The input file must end with .pdf.', 'Provide a PDF file path');\n    }\n    let fileStat;\n    try {\n        fileStat = await fs.stat(resolvedPath);\n    }\n    catch (error) {\n        if (error?.code === 'ENOENT') {\n            throw new CliError('FILE_NOT_FOUND', `File not found: ${resolvedPath}`, 'Provide a valid PDF file path');\n        }\n        throw new CliError('FILE_READ_ERROR', `Unable to inspect file: ${resolvedPath}`, 'Check file permissions and try again');\n    }\n    if (!fileStat.isFile()) {\n        throw new CliError('FILE_NOT_FOUND', `Not a file: ${resolvedPath}`, 'Provide a valid PDF file path');\n    }\n    if (fileStat.size < 100) {\n        throw new CliError('ARGUMENT', 'The PDF is too small. paperreview.ai requires at least 100 bytes.', 'Provide the final paper PDF');\n    }\n    if (fileStat.size > MAX_PDF_BYTES) {\n        throw new CliError('FILE_TOO_LARGE', 'The PDF is larger than paperreview.ai\\'s 10MB limit.', 'Compress the PDF or submit a smaller file');\n    }\n    let buffer;\n    try {\n        buffer = await fs.readFile(resolvedPath);\n    }\n    catch {\n        throw new CliError('FILE_READ_ERROR', `Unable to read file: ${resolvedPath}`, 'Check file permissions and try again');\n    }\n    return {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/paperreview/utils.js#L49-L85","documentation":"readPdfFile() calls fs.stat() to inspect the candidate PDF before reading it. If stat() fails for any reason other than ENOENT (which produces the dedicated FILE_NOT_FOUND 'File not found' error), the library wraps it as FILE_READ_ERROR 'Unable to inspect file: <path>'. This means the filesystem could not be queried at all — typically a permissions problem, a broken symlink loop, or a path component that is not a directory.","triggerScenarios":"Calling readPdfFile() when fs.stat(resolvedPath) rejects with something other than ENOENT: EACCES (no permission on the file or a parent directory), ELOOP (symlink loop), ENOTDIR (a path component is a file, e.g. /path/to.pdf/sub.pdf), or filesystem I/O errors.","commonSituations":"Running the CLI as a user lacking read permission on the file or a parent directory; passing a path under a symlink loop; passing a path whose parent component is actually a file; read-protected directories on shared CI runners.","solutions":["Check permissions with ls -l on the file and every parent directory; chmod/chown so the running user can access the path","Verify the path is valid: ensure no path component is a regular file and the path has no symlink loop (namei -l <path>)","Run stat <path> yourself to reproduce the underlying errno and fix accordingly","If on a CI runner, confirm the workspace/files were checked out with readable permissions"],"exampleFix":"// before\nawait readPdfFile(process.argv[2]);\n// after\nimport { accessSync, constants } from 'node:fs';\nconst p = process.argv[2];\naccessSync(p, constants.R_OK); // throws a clear EACCES before the CLI call\nawait readPdfFile(p);","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\nimport path from 'node:path';\nfunction canInspect(p) {\n    try {\n        const resolved = path.resolve(p);\n        fs.accessSync(resolved, fs.constants.R_OK | fs.constants.F_OK);\n        return true;\n    } catch (e) {\n        if (e.code === 'ENOENT') return false; // different error path\n        return false; // EACCES/ELOOP/ENOTDIR etc. -> would raise FILE_READ_ERROR\n    }\n}","typeGuard":"function isRegularFileStat(s) {\n    return typeof s === 'object' && s !== null && typeof s.isFile === 'function' && s.isFile();\n}","tryCatchPattern":"try {\n    const pdf = await readPdfFile(userPath);\n} catch (e) {\n    if (e?.code === 'FILE_READ_ERROR' && e.message.startsWith('Unable to inspect file')) {\n        console.error(`Cannot access ${userPath}: check permissions and that no parent path component is a file.`);\n    } else throw e;\n}","preventionTips":["Verify permissions (ls -l on path and parents) before invoking the CLI","Avoid passing paths under symlink loops or with a file as a parent component","Run the CLI as a user with access to the paper directory (not root-only locations)","Use namei -l <path> to trace permission issues along the whole path"],"tags":["filesystem","permissions","stat","cli"],"backgroundTag":"file-permission-denied","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}