{"record":{"id":"c80974abce8b6806","repo":"jackwener/OpenCLI","slug":"file-not-found-path","errorCode":null,"errorMessage":"File not found: ${path}","messagePattern":"File not found: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/_atlassian/shared.js","lineNumber":298,"sourceCode":"    if (n > maxValue) {\n        throw new ArgumentError(`${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport function requireExecute(args, commandName) {\n    if (args.execute !== true) {\n        throw new ArgumentError(`${commandName} requires --execute to perform a remote write`);\n    }\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) {","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/_atlassian/shared.js#L280-L316","documentation":"readUtf8File resolves --file input and stats it before reading. If stat() fails (the path does not exist or is inaccessible), it throws ArgumentError 'File not found: <path>' instead of leaking an ENOENT stack trace. This gives CLI users a clean, actionable message.","triggerScenarios":"Calling readUtf8File (typically via a --file CLI option) with a path that does not exist, or where a directory component is missing/unsearchable so stat() rejects.","commonSituations":"Typos in the file path; running from a different working directory than expected; relative path resolved against the wrong cwd in scripts/CI; file deleted between command composition and execution.","solutions":["Check the path exists (ls / fs.existsSync) and fix typos, then re-run.","Run the command from the directory where the file lives, or pass an absolute path.","Verify file-system permissions on every path component of the file."],"exampleFix":"// before\ncli jira comment --issue PROJ-1 --file ./notes.txt\n// after\ncli jira comment --issue PROJ-1 --file /home/user/notes.txt  # verified to exist","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises';\ntry { await stat(filePath); } catch { throw new Error(`File missing: ${filePath}`); }","typeGuard":"const isExistingFile = async (p) => { try { 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.startsWith('File not found')) {\n    console.error(`Path does not exist: ${p}. Check cwd and spelling.`);\n  }\n  throw err;\n}","preventionTips":["Use absolute paths in scripts instead of cwd-relative ones.","Check existence with fs.stat before invoking commands that take --file.","Avoid passing user-supplied paths without normalization (path.resolve)."],"tags":["filesystem","file-not-found","argument-validation","cli"],"backgroundTag":"file-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}