{"record":{"id":"111392dbe5e60ab7","repo":"santifer/career-ops","slug":"missing-required-field-context-key","errorCode":null,"errorMessage":"Missing required field: ${context}.${key}","messagePattern":"Missing required field: (.+?)\\.(.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"generate-cover-letter.mjs","lineNumber":36,"sourceCode":"import { fileURLToPath, pathToFileURL } from \"url\";\nimport { parseArgs } from \"util\";\nimport { assertFacts } from \"./verify-cv-facts.mjs\";\nimport { resolveTemplate } from \"./cv-templates.mjs\";\n\nconst OUTPUT_ROOT = resolve(\"output\");\n\n/** Sanitize a requested output filename and keep it under the output directory. */\nfunction safeOutputPath(raw) {\n  // Derive a sanitized filename from raw string (strip path separators and dots)\n  const filename = basename(raw).replace(/[^a-zA-Z0-9._-]/g, \"-\").replace(/\\.{2,}/g, \"-\");\n  return join(OUTPUT_ROOT, filename);\n}\n\n/** Assert that a payload object contains the required keys. */\nfunction _require(obj, keys, context) {\n  for (const key of keys) {\n    if (!obj || typeof obj !== \"object\" || !(key in obj)) {\n      throw new Error(`Missing required field: ${context}.${key}`);\n    }\n  }\n}\n\n/** Escape user-provided text before inserting it into generated HTML. */\nfunction escapeHtml(text) {\n  if (!text) return \"\";\n  return String(text)\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/'/g, \"&#39;\");\n}\n\n/** Add an HTTPS scheme to a profile URL when it is omitted. */\nfunction asUrl(value) {\n  return /^https?:\\/\\//i.test(value) ? value : `https://${value}`;","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/generate-cover-letter.mjs#L18-L54","documentation":"_require is a field-presence checker for the cover-letter JSON payload. It is called at three levels: payload must have candidate and letter; candidate must have name; letter must have role_title, opening, and profile_intro. The context prefix in the message identifies which level failed (e.g. payload.candidate, candidate.name, letter.opening).","triggerScenarios":"Payload JSON is missing the top-level letter object; candidate.name is absent; letter.opening or letter.profile_intro was omitted by the mode that generated the payload; a hand-written payload forgot a required field.","commonSituations":"The apply or cover mode generated an incomplete payload; an agent drafted the payload and missed role_title; the JSON was hand-edited and a key was removed.","solutions":["Inspect the payload JSON and ensure all required fields are present: payload.candidate, payload.candidate.name, payload.letter, payload.letter.role_title, payload.letter.opening, payload.letter.profile_intro.","Regenerate the payload from the cover mode ensuring the JD and cv.md have enough content to fill the required fields.","Validate the payload shape before passing it to generate-cover-letter.mjs."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function validateCoverPayload(payload) {\n  if (!payload || typeof payload !== 'object') throw new Error('payload must be an object');\n  if (!payload.candidate) throw new Error('payload.candidate is required');\n  if (!payload.candidate.name) throw new Error('candidate.name is required');\n  if (!payload.letter) throw new Error('payload.letter is required');\n  for (const key of ['role_title', 'opening', 'profile_intro']) {\n    if (!payload.letter[key]) throw new Error(`letter.${key} is required`);\n  }\n}","typeGuard":"/** @param {unknown} p */\nfunction isValidCoverPayload(p) {\n  if (!p || typeof p !== 'object') return false;\n  const payload = /** @type {Record<string, unknown>} */ (p);\n  const c = payload.candidate;\n  const l = payload.letter;\n  return (\n    !!c && typeof c === 'object' && 'name' in c &&\n    !!l && typeof l === 'object' &&\n    'role_title' in l && 'opening' in l && 'profile_intro' in l\n  );\n}","tryCatchPattern":null,"preventionTips":["Validate the payload JSON shape before passing to generate-cover-letter.mjs.","Ensure the mode that generates the payload fills all required fields.","Use a JSON schema or the type guard above at the boundary."],"tags":["validation","payload","cover-letter","required-fields"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}