santifer/career-ops · error · Error
Failed to read profile file at ${profileSource}: ${err.messa
Error message
Failed to read profile file at ${profileSource}: ${err.message} What it means
The catch around the default-path profile read wraps every failure — fs errors on config/profile.yml/CAREER_OPS_PROFILE, YAML syntax exceptions, and the nested error 307 — into this single message with the path and the underlying err.message. It guarantees callers of the no-argument path always get one predictable error shape for an unloadable profile.
Source
Thrown at scripts/export-ats-text.mjs:243
profileRaw = yaml.load(content);
if (!profileRaw || typeof profileRaw !== 'object') {
throw new Error(`Invalid YAML in profile file: ${customProfilePath}`);
}
} catch (err) {
throw new Error(`Failed to read profile file at ${customProfilePath}: ${err.message}`);
}
} else {
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');View on GitHub (pinned to 1696bec4d0)
Solutions
- Inspect the appended err.message (e.g. 'bad indentation of a mapping entry', 'EACCES') and fix that specific cause.
- Fix YAML formatting: spaces not tabs, quote strings containing special characters, keep one top-level mapping.
- Restore a known-good file: `cp config/profile.example.yml config/profile.yml`, edit values, rerun.
- Verify access: `ls -l config/profile.yml` and ensure it is a readable regular file owned by the running user.
Example fix
// before (unquoted colon breaks YAML) title: Senior: Backend Engineer // after title: "Senior: Backend Engineer"
Defensive patterns
Strategy: try-catch
Validate before calling
import { statSync } from 'node:fs';
import yaml from 'js-yaml';
const src = process.env.CAREER_OPS_PROFILE || 'config/profile.yml';
const st = statSync(src); // real fs error if unreadable/dir
yaml.load(readFileSync(src, 'utf8')); // real syntax error if malformed Try / catch
try {
const profile = loadProfile();
} catch (e) {
if (e.message.startsWith('Failed to read profile file at')) {
const cause = e.message.split(': ').slice(1).join(': ');
if (cause.includes('EACCES')) console.error('Fix permissions on config/profile.yml');
else if (cause.includes('ENOENT')) console.error('File vanished mid-run — recreate it');
else console.error('YAML syntax problem:', cause);
} else throw e;
} Prevention
- Pre-validate the default profile with js-yaml directly to see syntax errors before the wrapper masks them.
- Ensure CAREER_OPS_PROFILE points to a regular readable file, never a directory.
- Quote YAML values containing ':', '#', or leading special characters; use spaces, never tabs.
- Keep a known-good example file to restore from after bad edits.
When it happens
Trigger: existsSync passes but readFileSync then fails (permissions changed, file deleted in between, EISDIR), or yaml.load throws on malformed YAML, or the nested 'empty or invalid YAML' error fires — all rethrown here.
Common situations: config/profile.yml with tab indentation (js-yaml's classic failure); unquoted values containing ':' or '#'; CAREER_OPS_PROFILE pointing at a directory; unreadable file after chmod; Windows line-ending/BOM issues confusing the parser in edge setups.
Related errors
- Failed to read profile file at ${customProfilePath}: ${err.m
- arbeitsagentur: entry "${entry.name || '(unnamed)'}" has no
- wttj: the WTTJ board is global — configure explicit searches
- Profile configuration file not found at: ${customProfilePath
- Invalid YAML in profile file: ${customProfilePath}
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/4f58cf9e7f1fba94.
Report an issue: GitHub.