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

  1. Lint the file: npx yaml-lint config/profile.yml — it prints the exact line and column of the error.
  2. Fix what it reports: spaces for indentation, quote values containing ': ' or '#', close quotes and brackets.
  3. 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

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

Related errors


AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20). Data as JSON: /api/errors/cac05b757216c1ea. Report an issue: GitHub.