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

  1. Verify the path with fs.existsSync(customCvPath) and correct it; prefer absolute paths via path.resolve.
  2. Run from the repository root so relative paths like 'cv.md' resolve, or pass the repo-root-anchored absolute path.
  3. If the CV is genuinely optional for this run, pass null for customCvPath so the default/optional path is used instead.
  4. 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

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


AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01). Data as JSON: /api/errors/bdd859769b78e3dd. Report an issue: GitHub.