{"record":{"id":"0e53a2ca7f080f5f","repo":"jackwener/OpenCLI","slug":"file-could-not-be-read-path","errorCode":null,"errorMessage":"File could not be read: ${path}","messagePattern":"File could not be read: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/_atlassian/shared.js","lineNumber":307,"sourceCode":"    }\n}\n\nexport async function readUtf8File(filePath) {\n    const path = requireString(filePath, '--file');\n    let fileStat;\n    try {\n        fileStat = await stat(path);\n    } catch {\n        throw new ArgumentError(`File not found: ${path}`);\n    }\n    if (!fileStat.isFile()) {\n        throw new ArgumentError(`File must be a readable text file: ${path}`);\n    }\n    let raw;\n    try {\n        raw = await readFile(path);\n    } catch {\n        throw new ArgumentError(`File could not be read: ${path}`);\n    }\n    try {\n        return new TextDecoder('utf-8', { fatal: true }).decode(raw);\n    } catch {\n        throw new ArgumentError(`File could not be decoded as UTF-8 text: ${path}`);\n    }\n}\n\nexport function htmlEscape(value) {\n    return String(value ?? '')\n        .replace(/&/g, '&amp;')\n        .replace(/</g, '&lt;')\n        .replace(/>/g, '&gt;')\n        .replace(/\"/g, '&quot;');\n}\n\nexport function htmlToMarkdown(html) {\n    return coreHtmlToMarkdown(String(html ?? ''));","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/_atlassian/shared.js#L289-L325","documentation":"If the file exists and is a regular file but readFile() still rejects (permission denied, I/O error, race with deletion), readUtf8File throws ArgumentError 'File could not be read: <path>'. It normalizes low-level fs failures into a single user-facing message.","triggerScenarios":"stat() succeeds but readFile() rejects: no read permission, file deleted between stat and read, I/O error, or path is a symlink to an unreadable target.","commonSituations":"File owned by another user / chmod 600 while running under a service account; NFS or network mount hiccup; TOCTOU deletion in scripts; running in a container without the file mounted.","solutions":["Fix read permissions: chmod/chown or run as a user with access, then retry.","Confirm the file still exists at read time (was not removed by another process).","Verify volume mounts / network storage availability if running in a container or on a remote FS."],"exampleFix":"// before\n-rw-------  1 root root  512 notes.md   # run as non-root\n// after\nchmod 644 notes.md   # or run the CLI as the file owner","handlingStrategy":"validation","validationCode":"const s = await stat(p);\nawait access(p, fsConstants.R_OK); // throws EACCES early if unreadable","typeGuard":"const isReadableFile = async (p) => { try { await access(p, fsConstants.R_OK); return (await stat(p)).isFile(); } catch { return false; } };","tryCatchPattern":"try {\n  const text = await readUtf8File(p);\n} catch (err) {\n  if (err.name === 'ArgumentError' && err.message.includes('could not be read')) {\n    console.error(`Cannot read ${p}: check permissions and that the file still exists.`);\n  }\n  throw err;\n}","preventionTips":["Run the CLI as a user with read access to the input file.","Use chmod/chown (e.g. 644) for files consumed by automation.","Re-check existence right before reads in long-running scripts (TOCTOU)."],"tags":["filesystem","permissions","read-error","cli"],"backgroundTag":"file-read-permission-denied","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}