santifer/career-ops · error · Error
config/profile.yml is empty or invalid YAML: fill it in firs
Error message
config/profile.yml is empty or invalid YAML: fill it in first
What it means
This is the default-path twin of error 304: when the resolved profileSource (config/profile.yml or CAREER_OPS_PROFILE) exists but yaml.load returns null or a non-object, loadProfile throws this message. Like 304, it is immediately caught by the surrounding catch and rethrown as error 308 with the original cause appended, so users usually see the wrapper text.
Source
Thrown at scripts/export-ats-text.mjs:240
}
try {
const content = readFileSync(customProfilePath, 'utf8');
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}`);
}View on GitHub (pinned to 1696bec4d0)
Solutions
- Open config/profile.yml and ensure it contains a complete top-level YAML mapping with real values; re-copy from config/profile.example.yml and edit if in doubt.
- Validate independently: `node -e "const y=require('js-yaml'),f=require('fs');console.log(y.load(f.readFileSync('config/profile.yml','utf8')))"` and fix whatever prints null or throws.
- If the wrapper error (308) appears instead, follow its appended err.message to the specific YAML syntax problem.
Example fix
// before (profile.yml) --- // after (profile.yml) name: Ada Lovelace email: ada@example.com phone: "+886 900 000 000" location: Taipei linkedin: https://www.linkedin.com/in/ada
Defensive patterns
Strategy: type-guard
Validate before calling
import { readFileSync } from 'node:fs';
import yaml from 'js-yaml';
const doc = yaml.load(readFileSync('config/profile.yml', 'utf8'));
if (!doc || typeof doc !== 'object') {
throw new Error('config/profile.yml is empty or scalar — restore from config/profile.example.yml and edit');
} Type guard
function isValidProfileDoc(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length > 0;
} Try / catch
try {
const profile = loadProfile();
} catch (e) {
if (e.message.includes('empty or invalid YAML')) {
console.error('config/profile.yml parsed to nothing — refill it from config/profile.example.yml.');
} else throw e;
} Prevention
- After copying the example profile, verify the file parses to a non-empty object before committing to use.
- Guard against editor/truncation mishaps: check file size > 0 in setup scripts.
- Treat merge conflicts in profile.yml as blockers — resolve fully, don't commit marker-laden YAML.
When it happens
Trigger: config/profile.yml (or the CAREER_OPS_PROFILE target) exists but parses to null/primitive: empty file, comments-only file, bare scalar, lone '---', or YAML that js-yaml rejects and then the catch rewraps.
Common situations: Running `cp config/profile.example.yml config/profile.yml` and forgetting to edit it (template is fine, but truncated/emptied copies happen); a save failure zeroed the file; a botched sed/script edit; a merge conflict left only markers that parse oddly.
Related errors
- Invalid YAML in profile file: ${customProfilePath}
- arbeitsagentur: entry "${entry.name || '(unnamed)'}" has no
- wttj: the WTTJ board is global — configure explicit searches
- Failed to read profile file at ${customProfilePath}: ${err.m
- config/profile.yml not found: fill it in first
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/104fba7b6a9e2314.
Report an issue: GitHub.