{"record":{"id":"63c4102967d5ac5c","repo":"santifer/career-ops","slug":"unsupported-profile-photo-style-style-expecte","errorCode":null,"errorMessage":"Unsupported profile photo style: ${style} (expected rounded, circle, or square)","messagePattern":"Unsupported profile photo style: (.+?) \\(expected rounded, circle, or square\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"build-cv-html.mjs","lineNumber":114,"sourceCode":"  }\n  return escapeHtml(url);\n}\n\nfunction sanitizeImageSrc(src) {\n  if (typeof src !== 'string') return '';\n  const value = src.trim();\n  if (IMAGE_DATA_URL_RE.test(value)) return escapeHtml(value);\n  if (/^https?:\\/\\//i.test(value)) return sanitizeUrl(value);\n  return '';\n}\n\nasync function prepareCandidatePhoto(candidate) {\n  const c = candidate && typeof candidate === 'object' ? { ...candidate } : {};\n  const photo = typeof c.photo === 'string' ? c.photo.trim() : '';\n  const style = c.photo_style || c.photoStyle || 'rounded';\n\n  if (!PHOTO_STYLES.has(style)) {\n    throw new Error(`Unsupported profile photo style: ${style} (expected rounded, circle, or square)`);\n  }\n  c.photo_style = style;\n  if (!photo) {\n    c.photo = '';\n    return c;\n  }\n\n  if (photo.startsWith('data:')) {\n    if (!IMAGE_DATA_URL_RE.test(photo)) {\n      throw new Error('Unsupported profile photo data URL (expected base64 PNG, JPEG, WebP, or GIF)');\n    }\n    c.photo = photo;\n    return c;\n  }\n\n  if (/^https?:\\/\\//i.test(photo)) {\n    c.photo = photo;\n    return c;","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/build-cv-html.mjs#L96-L132","documentation":"Validation in `prepareCandidatePhoto` (build-cv-html.mjs): the photo style (`candidate.photo_style` or `candidate.photoStyle`, default `'rounded'`) must be in `PHOTO_STYLES` = `{'rounded','circle','square'}`. Any other value is rejected before rendering so the CSS class mapping stays bounded and the template doesn't silently fall back to a wrong shape.","triggerScenarios":"Passing `photo_style: 'round'`, `'circular'`, `'oval'`, `'rect'`, `'squircle'`, `'thumbnail'`, or any non-listed token; setting `photoStyle: 'Circle'` (case-sensitive — must be lowercase); typo in YAML/JSON config.","commonSituations":"Profile/config uses a synonym (`round`, `circular`); capitalization mismatch; user-facing UI exposes different labels than the renderer expects; config schema drift after an upgrade; agent picks a 'reasonable' word not in the set.","solutions":["Use exactly one of: `rounded`, `circle`, `square` (lowercase, exact spelling).","Map your UI/config labels onto these three before invoking build-cv-html.","Normalize case upstream: `style.toLowerCase()` won't fix synonyms but will fix `Circle`.","If you need a new shape, extend `PHOTO_STYLES` and add the matching CSS class.","Validate in the config loader so the error surfaces at config time, not render time."],"exampleFix":"// before (config/profile.yml)\nphoto_style: round\n# after\nphoto_style: rounded","handlingStrategy":"validation","validationCode":"const PHOTO_STYLES = new Set(['rounded', 'circle', 'square']);\nfunction normalizeStyle(s) {\n  const n = String(s || 'rounded').toLowerCase();\n  if (!PHOTO_STYLES.has(n)) throw new Error(`photo_style must be one of: ${[...PHOTO_STYLES].join(', ')}`);\n  return n;\n}","typeGuard":"function isPhotoStyle(s) {\n  return ['rounded', 'circle', 'square'].includes(String(s || '').toLowerCase());\n}","tryCatchPattern":null,"preventionTips":["Use one of: rounded, circle, square (lowercase exact).","Map UI labels (round, circular) onto these in the config loader.","Lowercase the value before validation to tolerate capitalization.","Extend PHOTO_STYLES intentionally if a new shape is needed."],"tags":["validation","config","build-cv-html","photo","enum"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}