{"record":{"id":"bdd859769b78e3dd","repo":"santifer/career-ops","slug":"cv-file-not-found-at-customcvpath","errorCode":null,"errorMessage":"CV file not found at: ${customCvPath}","messagePattern":"CV file not found at: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/export-ats-text.mjs","lineNumber":251,"sourceCode":"    if (!existsSync(profileSource)) {\n      throw new Error('config/profile.yml not found: fill it in first');\n    }\n    try {\n      const content = readFileSync(profileSource, 'utf8');\n      profileRaw = yaml.load(content);\n      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}","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/scripts/export-ats-text.mjs#L233-L269","documentation":"After loading the profile, loadProfile handles the CV: when the caller passes an explicit customCvPath, that file must exist, and its absence throws immediately. Unlike the default cv.md path (optional, silently skipped when missing), an explicitly provided CV path is treated as a hard requirement because the caller asserted it should be there.","triggerScenarios":"loadProfile(profilePath, 'cv-tailored.md') where cv-tailored.md doesn't exist at that path — typo'd filename, relative path resolved against the wrong cwd, a generated/tailored CV not yet written, or an env-style path passed positionally by mistake.","commonSituations":"Referencing a tailored CV in output/ that was cleaned or gitignored; running from a subdirectory so 'cv.md' relative path misses; pointing at the wrong extension (cv.pdf instead of cv.md); argument order confusion passing a profile path into the cv slot where it doesn't exist as given.","solutions":["Verify the path with fs.existsSync(customCvPath) and correct it; prefer absolute paths via path.resolve.","Run from the repository root so relative paths like 'cv.md' resolve, or pass the repo-root-anchored absolute path.","If the CV is genuinely optional for this run, pass null for customCvPath so the default/optional path is used instead.","Ensure the tailored CV is generated (e.g. via the pdf mode) before invoking the ATS export that references it."],"exampleFix":"// before\nloadProfile('config/profile.yml', 'output/cv-tailored.md'); // not generated yet\n\n// after\nimport { existsSync } from 'node:fs';\nconst cv = 'output/cv-tailored.md';\nconst cvArg = existsSync(cv) ? cv : null; // fall back to optional cv.md\nloadProfile('config/profile.yml', cvArg);","handlingStrategy":"validation","validationCode":"import { existsSync, statSync } from 'node:fs';\nimport path from 'node:path';\nconst cv = customCvPath && path.resolve(process.cwd(), customCvPath);\nif (cv && !(existsSync(cv) && statSync(cv).isFile())) {\n  throw new Error(`CV not found at ${cv}; generate it or pass null to use optional cv.md`);\n}\nloadProfile(profilePath, cv);","typeGuard":"function isExistingFile(p) {\n  try { return Boolean(p) && statSync(p).isFile(); } catch { return false; }\n}","tryCatchPattern":"try {\n  const result = loadProfile(profilePath, customCvPath);\n} catch (e) {\n  if (e.message.startsWith('CV file not found')) {\n    console.warn(`${e.message} — proceeding with profile-only data`);\n    return loadProfile(profilePath, null); // cv.md is optional by design\n  }\n  throw e;\n}","preventionTips":["Generate tailored CVs before the export step that references them; check existsSync in the pipeline.","Pass absolute, repo-root-resolved paths for customCvPath to avoid cwd surprises.","Remember the asymmetry: explicit cv path = required, default cv.md = optional — pass null when the CV genuinely may be absent.","Watch argument order: (customProfilePath, customCvPath) — swapping them produces this not-found error from a profile path checked as a CV."],"tags":["filesystem","missing-file","cv","path-resolution"],"backgroundTag":"config-file-not-found","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}