{"record":{"id":"cac05b757216c1ea","repo":"santifer/career-ops","slug":"failed-to-parse-profile-yml-err-message","errorCode":null,"errorMessage":"⚠️   Failed to parse profile.yml: ${err.message}","messagePattern":"⚠️   Failed to parse profile\\.yml: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"openai-tailor.mjs","lineNumber":328,"sourceCode":"// Clean up markdown block wrapping if the LLM adds it despite instructions\ntailoredHtml = tailoredHtml.replace(/^\\s*```(html)?\\s*/i, '').replace(/\\s*```\\s*$/, '');\n\n// ---------------------------------------------------------------------------\n// Save tailored HTML\n// ---------------------------------------------------------------------------\ntry {\n  if (!existsSync(PATHS.output)) {\n    mkdirSync(PATHS.output, { recursive: true });\n  }\n\n  let candidateName = 'candidate';\n  try {\n    const profile = yaml.load(profileContent);\n    if (profile && profile.name) {\n      candidateName = profile.name;\n    }\n  } catch (err) {\n    console.warn(`⚠️   Failed to parse profile.yml: ${err.message}`);\n  }\n  candidateName = candidateName\n    .toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');\n\n  const filename = `cv-${candidateName}-${companySlug}.html`;\n  const htmlPath = join(PATHS.output, filename);\n\n  writeFileSync(htmlPath, tailoredHtml, 'utf-8');\n  console.log(`\\n✅  Tailored HTML saved: ${htmlPath}`);\n\n  // Print next steps\n  const pdfFilename = `cv-${candidateName}-${companySlug}-${roleSlug}-${new Date().toISOString().split('T')[0]}.pdf`;\n  const reportNumMatch = reportFilename.match(/^(\\d+)-/);\n  const reportNum = reportNumMatch ? reportNumMatch[1] : '001';\n\n  console.log(`\\n📄  Next step (generate PDF):\\n    node generate-pdf.mjs output/${filename} output/${pdfFilename} --format=letter --report=${reportNum}\\n`);\n\n} catch (err) {","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/santifer/career-ops/blob/60398d6549a46f5266929538af21cfab94badc75/openai-tailor.mjs#L310-L346","documentation":"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.","triggerScenarios":"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.","commonSituations":"Quick hand-edits of the profile; content pasted from rich-text sources; first-time users unfamiliar with YAML's no-tabs rule.","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-."],"exampleFix":"# before — config/profile.yml (invalid YAML)\nname: Chris: P.\nskills:\n\t- llm-ops        # tab indentation is illegal in YAML\n# after\nname: \"Chris: P.\"\nskills:\n  - llm-ops       # spaces only, colon-containing value quoted\n","handlingStrategy":"validation","validationCode":"import yaml from 'js-yaml';\nimport { readFileSync } from 'node:fs';\n// run BEFORE the paid tailor call — err.mark gives the exact line:column\ntry {\n  yaml.load(readFileSync('config/profile.yml', 'utf-8'));\n} catch (err) {\n  console.error(`profile.yml invalid at ${err.mark?.line + 1}:${err.mark?.column + 1} — ${err.reason}`);\n  process.exit(1);\n}","typeGuard":"const parsesAsRecord = (text) => {\n  try {\n    const v = yaml.load(text);\n    return typeof v === 'object' && v !== null && !Array.isArray(v);\n  } catch {\n    return false;\n  }\n};","tryCatchPattern":"try {\n  const profile = yaml.load(profileContent);\n  candidateName = profile?.name ?? 'candidate';\n} catch (err) {\n  // use err.mark (line/column) and err.reason to point at the exact character\n  console.warn(`Failed to parse profile.yml: line ${err.mark?.line + 1}: ${err.reason}`);\n}","preventionTips":["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"],"tags":["yaml","js-yaml","config","parse-error"],"backgroundTag":"yaml-syntax-error","analyzedSha":"60398d6549a46f5266929538af21cfab94badc75","analyzedAt":"2026-08-20T23:00:06.764Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}