{"record":{"id":"aba5e1cebe2553e7","repo":"santifer/career-ops","slug":"unknown-template-format-format","errorCode":null,"errorMessage":"Unknown template format: ${format}","messagePattern":"Unknown template format: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cv-sections-core.mjs","lineNumber":144,"sourceCode":"    projects: new RegExp(String.raw`%{4,}\\s+PROJECTS\\s+%{4,}[\\s\\S]*?` + TEX_BOUNDARY),\n    education: new RegExp(String.raw`%{4,}\\s+Education\\s+%{4,}[\\s\\S]*?` + TEX_BOUNDARY),\n    awards: new RegExp(String.raw`%{4,}\\s+AWARDS\\s+%{4,}[\\s\\S]*?` + TEX_BOUNDARY),\n    skills: new RegExp(String.raw`%{4,}\\s+Technical Skills\\s+%{4,}[\\s\\S]*?` + TEX_END_SENTINEL, 'm'),\n  },\n};\n\nexport const OPTIONAL_SECTIONS = ['competencies', 'experience', 'projects', 'education', 'certifications', 'awards', 'interests', 'skills'];\n\nexport function isEmptySection(payload, section) {\n  const entries = payload?.[section];\n  return !Array.isArray(entries) || entries.length === 0;\n}\n\n// Remove every optional section that has no entries in `payload`. Returns the\n// template unchanged when both are populated.\nexport function stripEmptySections(template, payload, format) {\n  const patterns = PATTERNS[format];\n  if (!patterns) throw new Error(`Unknown template format: ${format}`);\n\n  let out = template;\n  for (const section of OPTIONAL_SECTIONS) {\n    const pattern = patterns[section];\n    if (!pattern) continue; // this format's template has no marker for this section\n    if (isEmptySection(payload, section)) {\n      // A non-matching pattern is a no-op here by design — see the Skills\n      // sentinel note above: no sentinel means no strip, never a fallback to\n      // a looser boundary.\n      out = out.replace(pattern, '');\n    }\n  }\n  return out;\n}\n","sourceCodeStart":126,"sourceCodeEnd":159,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/cv-sections-core.mjs#L126-L159","documentation":"stripEmptySections removes optional sections with no payload entries, but it looks up marker patterns via PATTERNS[format] first. If the format string isn't a registered key in PATTERNS (only formats with defined section-marker patterns qualify), it throws instead of guessing, since without patterns it cannot know what to strip.","triggerScenarios":"Calling stripEmptySections(template, payload, 'md') or any format other than the registered keys (e.g. 'html'/'tex' as wired into the builders); passing undefined format from an unvalidated option; a typo like 'HTML' if PATTERNS keys are lowercase.","commonSituations":"Adding a new output format without registering its PATTERNS entry; calling the shared core directly from custom tooling with an ad-hoc format name; case-mismatched format strings from CLI parsing.","solutions":["Pass a registered format ('html' or 'tex') as the third argument.","Check the PATTERNS map in cv-sections-core.mjs for valid keys.","Fix case sensitivity ('HTML' → 'html').","If adding a new format, register a full PATTERNS entry for it first."],"exampleFix":"// before\nstripEmptySections(template, payload, 'markdown');\n\n// after\nstripEmptySections(template, payload, 'html');","handlingStrategy":"validation","validationCode":"import { PATTERNS } from './cv-sections-core.mjs';\nfunction canStrip(format) {\n  return Object.prototype.hasOwnProperty.call(PATTERNS, format);\n}\n// if (!canStrip(format)) throw new Error(`stripEmptySections: unregistered format '${format}'`);","typeGuard":"const hasPatterns = (fmt) => fmt != null && typeof PATTERNS[fmt] === 'object';","tryCatchPattern":"try {\n  out = stripEmptySections(tpl, payload, format);\n} catch (e) {\n  if (e.message.startsWith('Unknown template format:')) {\n    console.error(`Format '${format}' has no section patterns; returning template unstripped`);\n    out = tpl;\n  } else throw e;\n}","preventionTips":["Derive the format value from the same constant list the builders use.","Register a PATTERNS entry before introducing any new format.","Test stripEmptySections for each supported format in CI.","Avoid hand-typing format strings — pass them through from the CLI dispatch table."],"tags":["template","format","validation"],"backgroundTag":"unsupported-config-value","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"}