santifer/career-ops · error · Error
CV file not found at: ${customCvPath}
Error message
CV file not found at: ${customCvPath} What it means
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.
Source
Thrown at scripts/export-ats-text.mjs:251
if (!existsSync(profileSource)) {
throw new Error('config/profile.yml not found: fill it in first');
}
try {
const content = readFileSync(profileSource, 'utf8');
profileRaw = yaml.load(content);
if (!profileRaw || typeof profileRaw !== 'object') {
throw new Error('config/profile.yml is empty or invalid YAML: fill it in first');
}
} catch (err) {
throw new Error(`Failed to read profile file at ${profileSource}: ${err.message}`);
}
}
let cvData = {};
const cvSource = customCvPath || process.env.CAREER_OPS_CV || 'cv.md';
if (customCvPath) {
if (!existsSync(customCvPath)) {
throw new Error(`CV file not found at: ${customCvPath}`);
}
try {
const cvText = readFileSync(customCvPath, 'utf8');
cvData = parseCvMarkdown(cvText);
} catch (err) {
throw new Error(`Failed to read CV file at ${customCvPath}: ${err.message}`);
}
} else if (existsSync(cvSource)) {
try {
const cvText = readFileSync(cvSource, 'utf8');
cvData = parseCvMarkdown(cvText);
} catch {
// cv.md is optional if profile supplies necessary fields
}
}
return normalizeProfile(profileRaw, cvData);
}View on GitHub (pinned to 1696bec4d0)
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.
Example fix
// before
loadProfile('config/profile.yml', 'output/cv-tailored.md'); // not generated yet
// after
import { existsSync } from 'node:fs';
const cv = 'output/cv-tailored.md';
const cvArg = existsSync(cv) ? cv : null; // fall back to optional cv.md
loadProfile('config/profile.yml', cvArg); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, statSync } from 'node:fs';
import path from 'node:path';
const cv = customCvPath && path.resolve(process.cwd(), customCvPath);
if (cv && !(existsSync(cv) && statSync(cv).isFile())) {
throw new Error(`CV not found at ${cv}; generate it or pass null to use optional cv.md`);
}
loadProfile(profilePath, cv); Type guard
function isExistingFile(p) {
try { return Boolean(p) && statSync(p).isFile(); } catch { return false; }
} Try / catch
try {
const result = loadProfile(profilePath, customCvPath);
} catch (e) {
if (e.message.startsWith('CV file not found')) {
console.warn(`${e.message} — proceeding with profile-only data`);
return loadProfile(profilePath, null); // cv.md is optional by design
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.
Related errors
- Profile configuration file not found at: ${customProfilePath
- Profile photo not found or unreadable: ${photo} (${err.code
- ⚠️ ${label} not found: ${path}
- Unsupported profile photo style: ${style} (expected rounded,
- Unsupported profile photo data URL (expected base64 PNG, JPE
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/bdd859769b78e3dd.
Report an issue: GitHub.