santifer/career-ops · warning
⚠️ Failed to parse profile.yml: ${err.message}
Error message
⚠️ Failed to parse profile.yml: ${err.message} What it means
js-yaml's yaml.load threw a YAMLException while parsing config/profile.yml inside openai-tailor.mjs — the file has a syntax error (tab indentation, an unclosed quote or bracket, an unquoted value containing ': '). The script degrades gracefully: candidateName falls back to 'candidate', so the tailored CV is saved as cv-candidate-{company}.html instead of cv-{your-name}-{company}.html. The tailoring itself still runs to completion.
Source
Thrown at openai-tailor.mjs:328
// Clean up markdown block wrapping if the LLM adds it despite instructions
tailoredHtml = tailoredHtml.replace(/^\s*```(html)?\s*/i, '').replace(/\s*```\s*$/, '');
// ---------------------------------------------------------------------------
// Save tailored HTML
// ---------------------------------------------------------------------------
try {
if (!existsSync(PATHS.output)) {
mkdirSync(PATHS.output, { recursive: true });
}
let candidateName = 'candidate';
try {
const profile = yaml.load(profileContent);
if (profile && profile.name) {
candidateName = profile.name;
}
} catch (err) {
console.warn(`⚠️ Failed to parse profile.yml: ${err.message}`);
}
candidateName = candidateName
.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
const filename = `cv-${candidateName}-${companySlug}.html`;
const htmlPath = join(PATHS.output, filename);
writeFileSync(htmlPath, tailoredHtml, 'utf-8');
console.log(`\n✅ Tailored HTML saved: ${htmlPath}`);
// Print next steps
const pdfFilename = `cv-${candidateName}-${companySlug}-${roleSlug}-${new Date().toISOString().split('T')[0]}.pdf`;
const reportNumMatch = reportFilename.match(/^(\d+)-/);
const reportNum = reportNumMatch ? reportNumMatch[1] : '001';
console.log(`\n📄 Next step (generate PDF):\n node generate-pdf.mjs output/${filename} output/${pdfFilename} --format=letter --report=${reportNum}\n`);
} catch (err) {View on GitHub (pinned to 60398d6549)
Solutions
- Lint the file: npx yaml-lint config/profile.yml — it prints the exact line and column of the error.
- Fix what it reports: spaces for indentation, quote values containing ': ' or '#', close quotes and brackets.
- Re-run the tailor and confirm the output filename now starts with cv-{your-name}- instead of cv-candidate-.
Example fix
# before — config/profile.yml (invalid YAML) name: Chris: P. skills: - llm-ops # tab indentation is illegal in YAML # after name: "Chris: P." skills: - llm-ops # spaces only, colon-containing value quoted
Defensive patterns
Strategy: validation
Validate before calling
import yaml from 'js-yaml';
import { readFileSync } from 'node:fs';
// run BEFORE the paid tailor call — err.mark gives the exact line:column
try {
yaml.load(readFileSync('config/profile.yml', 'utf-8'));
} catch (err) {
console.error(`profile.yml invalid at ${err.mark?.line + 1}:${err.mark?.column + 1} — ${err.reason}`);
process.exit(1);
} Type guard
const parsesAsRecord = (text) => {
try {
const v = yaml.load(text);
return typeof v === 'object' && v !== null && !Array.isArray(v);
} catch {
return false;
}
}; Try / catch
try {
const profile = yaml.load(profileContent);
candidateName = profile?.name ?? 'candidate';
} catch (err) {
// use err.mark (line/column) and err.reason to point at the exact character
console.warn(`Failed to parse profile.yml: line ${err.mark?.line + 1}: ${err.reason}`);
} Prevention
- Add yaml-lint (or a yaml.load smoke test) to pre-commit for config/profile.yml
- Never use tabs in YAML; configure the editor to insert spaces
- Quote any value containing ': ', '#', or leading/trailing spaces
When it happens
Trigger: Editing config/profile.yml with a tab-indented line; name: Chris: P. left unquoted; a smart quote pasted from formatted docs or chat; an unclosed " or [ or { ; duplicate keys under strict parsing.
Common situations: Quick hand-edits of the profile; content pasted from rich-text sources; first-time users unfamiliar with YAML's no-tabs rule.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Cannot read benchmarks at ${path}: ${err.message}
- Malformed benchmarks file at ${path}: expected a top-level "
- Invalid page budget "${maxPages}". Use a positive integer.
- Malformed states file at ${statesPath}: expected a top-level
- Malformed states file at ${statesPath}: expected a top-level
AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20).
Data as JSON: /api/errors/cac05b757216c1ea.
Report an issue: GitHub.