{"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":null,"httpStatus":null,"severity":"error","filePath":"generate-cover-letter.mjs","lineNumber":78,"sourceCode":"      ? posix.slice(\"output/\".length)\n      : posix;\n  const candidate = resolve(OUTPUT_ROOT, relativeToRoot);\n  if (containedInOutput(candidate)) return candidate;\n\n  throw new Error(`Refusing to write the cover letter outside output/: ${raw}`);\n}\n\n/** True when absPath is a file (not output/ itself) still inside OUTPUT_ROOT. */\nfunction containedInOutput(absPath) {\n  const rel = relative(OUTPUT_ROOT, absPath);\n  return rel !== \"\" && !rel.startsWith(\"..\") && !isAbsolute(rel);\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":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/generate-cover-letter.mjs#L60-L96","documentation":"_require in generate-cover-letter.mjs asserts that a payload object (e.g. candidate, job, company sections) contains every required key for HTML generation. If the object is missing/null/not-an-object or lacks a key, it throws naming the context (section) and key so the caller knows exactly which payload field to supply.","triggerScenarios":"Calling the cover-letter generator with a payload missing a required field, e.g. { candidate: {...}, job: { title } } without job.company; passing null/undefined for a nested section; a typo in a key name (companyName vs company).","commonSituations":"Hand-written JSON payloads for the module API; a script building the payload conditionally and skipping an optional-looking field that is actually required; schema drift after a template update added a new required key.","solutions":["Add the missing `${context}.${key}` field to your payload before calling the generator.","Log the whole payload object and compare against the template's _require(...) call list for that context.","Fix key typos by diffing your payload keys against the expected field names.","Add a pre-flight validation that checks all required keys for each section before invoking."],"exampleFix":"// before\nconst payload = { candidate: {name: 'A'}, job: {title: 'Eng'} };\n// after\nconst payload = { candidate: {name: 'A'}, job: {title: 'Eng', company: 'Acme'} };","handlingStrategy":"type-guard","validationCode":"function requireKeys(obj, keys, ctx) { for (const k of keys) if (!obj || typeof obj !== 'object' || !(k in obj)) throw new Error(`Missing ${ctx}.${k}`); }\nrequireKeys(payload.job, ['title','company'], 'job');","typeGuard":"const hasKeys = (obj, keys) => !!obj && typeof obj === 'object' && keys.every(k => k in obj);","tryCatchPattern":"try { generateCoverLetter(payload); } catch (e) { const m = e.message.match(/Missing required field: ([\\w.]+)/); if (m) { console.error(`Payload missing: ${m[1]}`); process.exit(2); } throw e; }","preventionTips":["Keep a single payload-building function that always sets every required key.","Validate payloads with a schema (or the module's own _require list) before calling.","Diff payload keys against the template's required fields after any template update.","Watch for typos between payload key names and the documented field names."],"tags":["validation","payload","missing-field"],"backgroundTag":"missing-required-argument","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}