santifer/career-ops · error · Error
CV file not found at
Error message
CV file not found at: ${customCvPath} What it means
Thrown by loadProfile() when an explicitly supplied customCvPath (second argument) does not exist on disk. The CV is optional (default cv.md is skipped silently if absent), but an explicitly requested CV file must exist — hence the fail-fast check before reading.
Solutions
- Verify the path exists: ls the exact customCvPath value and correct typos.
- Use path.resolve() for an absolute path so it does not depend on the current working directory.
- Pass null to fall back to the default cv.md (which is silently optional) if a CV is not required.
- Check the CAREER_OPS_CV env var resolves to an existing file before passing it through.
Example fix
// before const profile = loadProfile(null, 'cv.md'); // cwd is scripts/, file is at repo root // after const profile = loadProfile(null, path.resolve(__dirname, '..', 'cv.md'));
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'node:fs';
const cvPath = path.resolve(__dirname, 'cv.md');
if (!existsSync(cvPath)) {
console.warn(`CV not found at ${cvPath}; proceeding without CV data`);
}
const profile = loadProfile(null, existsSync(cvPath) ? cvPath : null); Prevention
- Pass absolute, path.resolve()'d CV paths — never cwd-relative strings.
- Remember a CV is optional: pass null to fall back to the silently-skipped default cv.md.
- Keep cv.md at the repo root and don't rename it without updating callers.
- Ensure CI checks out/generates cv.md before running export scripts.
When it happens
Trigger: Calling loadProfile(profilePath, 'cv_old.md') where that CV file is missing: typo, deleted file, wrong cwd for a relative path, or an env-var CAREER_OPS_CV pointing nowhere when passed through.
Common situations: Renamed cv.md to something else; running the export script from a subdirectory; CI missing the CV artifact; pointing at a CV in another repo that was not cloned.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- ⚠️ config/profile.yml cv.sections lists only
- ⚠️ config/profile.yml cv.sections lists
- ⚠️ config/profile.yml cv.sections lists
- ⚠️ config/profile.yml cv.sections names
- config/profile.yml not found: fill it in first
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/bdd859769b78e3dd.
Report an issue: GitHub.
Appendix: 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 aac998c7ed)