santifer/career-ops · error · Error

Failed to read CV file at ${customCvPath}: ${err.message}

Error message

Failed to read CV file at ${customCvPath}: ${err.message}

What it means

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.

Source

Thrown at scripts/export-ats-text.mjs:257

      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);
}

/**
 * Formats profile object into structured plain-text section blocks.
 */
export function formatAtsText(profile = {}, options = {}) {
  const normalized = normalizeProfile(profile);

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. 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
  2. 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)
  3. Run the read manually (`cat <path>`) to see the underlying err.message included in the error and address it directly
  4. If the default CV should be used instead, drop the custom path so the script falls back to the default cvSource branch

Example fix

// before
node scripts/export-ats-text.mjs --cv ./cv.pdf
// Error: Failed to read CV file at ./cv.pdf: ...
// after: export the CV as UTF-8 markdown first
pandoc cv.pdf -o cv.md
node scripts/export-ats-text.mjs --cv ./cv.md
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync, statSync, accessSync, constants } from 'fs';
function cvFileIsReadable(p) {
  if (!p || !existsSync(p)) return false;
  if (!statSync(p).isFile()) return false;
  try { accessSync(p, constants.R_OK); return true; } catch { return false; }
}
// call before: if (!cvFileIsReadable(customCvPath)) { /* fix path/perms or fall back to default cvSource */ }

Try / catch

try {
  cvData = parseCvMarkdown(readFileSync(customCvPath, 'utf8'));
} catch (err) {
  console.error(`CV unreadable/unparseable (${customCvPath}): ${err.message}; falling back to default cv.md`);
  cvData = parseCvMarkdown(readFileSync(DEFAULT_CV, 'utf8'));
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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