{"record":{"id":"3a4b2d5771c2e2e3","repo":"santifer/career-ops","slug":"failed-to-read-cv-file-at-customcvpath-err-m","errorCode":null,"errorMessage":"Failed to read CV file at ${customCvPath}: ${err.message}","messagePattern":"Failed to read CV file at (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/export-ats-text.mjs","lineNumber":257,"sourceCode":"      if (!profileRaw || typeof profileRaw !== 'object') {\n        throw new Error('config/profile.yml is empty or invalid YAML: fill it in first');\n      }\n    } catch (err) {\n      throw new Error(`Failed to read profile file at ${profileSource}: ${err.message}`);\n    }\n  }\n\n  let cvData = {};\n  const cvSource = customCvPath || process.env.CAREER_OPS_CV || 'cv.md';\n  if (customCvPath) {\n    if (!existsSync(customCvPath)) {\n      throw new Error(`CV file not found at: ${customCvPath}`);\n    }\n    try {\n      const cvText = readFileSync(customCvPath, 'utf8');\n      cvData = parseCvMarkdown(cvText);\n    } catch (err) {\n      throw new Error(`Failed to read CV file at ${customCvPath}: ${err.message}`);\n    }\n  } else if (existsSync(cvSource)) {\n    try {\n      const cvText = readFileSync(cvSource, 'utf8');\n      cvData = parseCvMarkdown(cvText);\n    } catch {\n      // cv.md is optional if profile supplies necessary fields\n    }\n  }\n\n  return normalizeProfile(profileRaw, cvData);\n}\n\n/**\n * Formats profile object into structured plain-text section blocks.\n */\nexport function formatAtsText(profile = {}, options = {}) {\n  const normalized = normalizeProfile(profile);","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/scripts/export-ats-text.mjs#L239-L275","documentation":"loadProfile in scripts/export-ats-text.mjs reads the user's CV markdown and parses it. When an explicit custom CV path was provided and readFileSync/parseCvMarkdown throws (missing permissions, unreadable file, or parse failure), the script wraps the underlying error in 'Failed to read CV file at <path>' so the developer knows which CV file could not be processed. Note that a missing file is handled earlier with a distinct 'CV file not found' error, so this error means the file exists but reading or parsing it failed.","triggerScenarios":"Calling loadProfile (or the script CLI) with --cv/customCvPath pointing to an existing file that: cannot be read by the current OS user (permission denied), is a directory, is binary/invalid UTF-8 (readFileSync throws ERR_INVALID_ARG_VALUE or similar), or whose content makes parseCvMarkdown throw.","commonSituations":"Passing a path with a typo that happens to point to a directory; running the script as a user without read permission on the CV (e.g. chmod 600 owned by another user); feeding a PDF or DOCX renamed to .md; a CV with markup that trips the markdown parser.","solutions":["Check that the custom CV path points to a regular readable file (not a directory) and that the current user has read permission; fix with chmod/chown if needed","Convert the CV to UTF-8 plain-text markdown (e.g. `file -bi cv.md` to verify encoding; re-export from PDF/DOCX to .md)","Run the read manually (`cat <path>`) to see the underlying err.message included in the error and address it directly","If the default CV should be used instead, drop the custom path so the script falls back to the default cvSource branch"],"exampleFix":"// before\nnode scripts/export-ats-text.mjs --cv ./cv.pdf\n// Error: Failed to read CV file at ./cv.pdf: ...\n// after: export the CV as UTF-8 markdown first\npandoc cv.pdf -o cv.md\nnode scripts/export-ats-text.mjs --cv ./cv.md","handlingStrategy":"validation","validationCode":"import { existsSync, statSync, accessSync, constants } from 'fs';\nfunction cvFileIsReadable(p) {\n  if (!p || !existsSync(p)) return false;\n  if (!statSync(p).isFile()) return false;\n  try { accessSync(p, constants.R_OK); return true; } catch { return false; }\n}\n// call before: if (!cvFileIsReadable(customCvPath)) { /* fix path/perms or fall back to default cvSource */ }","typeGuard":null,"tryCatchPattern":"try {\n  cvData = parseCvMarkdown(readFileSync(customCvPath, 'utf8'));\n} catch (err) {\n  console.error(`CV unreadable/unparseable (${customCvPath}): ${err.message}; falling back to default cv.md`);\n  cvData = parseCvMarkdown(readFileSync(DEFAULT_CV, 'utf8'));\n}","preventionTips":["Verify the custom CV is a regular, readable UTF-8 file before passing it (file -bi, ls -l)","Keep CVs in plain-text markdown, never PDF/DOCX renamed to .md","Run export scripts from an account with read access to all input files","When the file fails, fall back to the default cv.md rather than aborting"],"tags":["filesystem","file-read","cv-parsing","node"],"backgroundTag":"file-read-failed","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}