{"record":{"id":"2386ab73775e2534","repo":"juspay/hyperswitch","slug":"invalid-hex-color-hex-2386ab","errorCode":null,"errorMessage":"Invalid HEX color: \"${hex}\"","messagePattern":"Invalid HEX color: \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/router/src/core/payment_link/payment_link_status/status.js","lineNumber":29,"sourceCode":"  } catch (e) {\n    console.error(\"Error decoding and parsing string URI:\", e);\n    return uri;\n  }\n}\n\n/**\n * Ref - https://github.com/onury/invert-color/blob/master/lib/cjs/invert.js\n */\nfunction padz(str, len) {\n  if (len === void 0) {\n    len = 2;\n  }\n  return (new Array(len).join(\"0\") + str).slice(-len);\n}\nfunction hexToRgbArray(hex) {\n  if (hex.slice(0, 1) === \"#\") hex = hex.slice(1);\n  var RE_HEX = /^(?:[0-9a-f]{3}){1,2}$/i;\n  if (!RE_HEX.test(hex)) throw new Error('Invalid HEX color: \"' + hex + '\"');\n  if (hex.length === 3) {\n    hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n  }\n  return [\n    parseInt(hex.slice(0, 2), 16),\n    parseInt(hex.slice(2, 4), 16),\n    parseInt(hex.slice(4, 6), 16),\n  ];\n}\nfunction toRgbArray(c) {\n  if (!c) throw new Error(\"Invalid color value\");\n  if (Array.isArray(c)) return c;\n  return typeof c === \"string\" ? hexToRgbArray(c) : [c.r, c.g, c.b];\n}\nfunction getLuminance(c) {\n  var i, x;\n  var a = [];\n  for (i = 0; i < c.length; i++) {","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/juspay/hyperswitch/blob/9b8b89dc378b62c9a6feda647bad4719d2de7699/crates/router/src/core/payment_link/payment_link_status/status.js#L11-L47","documentation":"Identical vendored invert-color code, but embedded in the payment link status page (crates/router/src/core/payment_link/payment_link_status/status.js). hexToRgbArray() throws when, after removing a leading '#', the string is not exactly 3 or 6 hex digits. This page re-renders branding colours while polling the payment status, so an invalid branding hex breaks the status view.","triggerScenarios":"Opening the payment link status page for a link whose theme or payment_button_colour is a named colour ('blue'), an rgb()/rgba() string, 4/8-digit hex, or contains whitespace/invalid characters; invert() is invoked on those values during status-page colour setup.","commonSituations":"Same root cause as the initiate page: branding values persisted without hex validation; values copied from CSS or a design tool ('#1A2B3CCC' from Figma exports alpha hex); inconsistent data between the initiate and status payloads after a partial fix on only one page.","solutions":["Fix the stored branding value to a strict 3/6-digit hex on the business/merchant profile or the payment link","Apply the same defensive default in status.js as in payment_link.js before calling invert()","Add hex validation where branding is authored so both pages stop receiving bad values","Keep the two vendored copies in sync — a fix applied to only one file leaves the other throwing"],"exampleFix":"// before (status.js)\nvar contrastBWColor = invert(primaryColor, true);\n\n// after\nvar HEX_RE = /^#?(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;\nvar primaryColor =\n  typeof theme === 'string' && HEX_RE.test(theme.trim()) ? theme : '#1a2b3c';\nvar contrastBWColor = invert(primaryColor, true);","handlingStrategy":"validation","validationCode":"const HEX_RE = /^#?(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;\nfunction normalizeHexColor(c, fallback = '#1a2b3c') {\n  return typeof c === 'string' && HEX_RE.test(c.trim()) ? c.trim() : fallback;\n}\n// use in status.js render path:\nvar theme = normalizeHexColor(statusPayload.theme);","typeGuard":"/** @param {unknown} c @returns {c is string} */\nfunction isHexColor(c) {\n  return typeof c === 'string' && /^#?(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test(c.trim());\n}","tryCatchPattern":"try {\n  contrastBWColor = invert(theme, true);\n} catch (e) {\n  if (/Invalid HEX color/.test(e.message)) {\n    contrastBWColor = '#ffffff';\n  } else {\n    throw e;\n  }\n}","preventionTips":["Apply the same hex validation to the status page as to the initiate page","Fix branding data at the source (API/DB) so neither page receives bad values","Test the status page with the same branding edge cases as the initiate page"],"tags":["payment-link","payment-status","hex-color","branding","client-side"],"backgroundTag":null,"analyzedSha":"9b8b89dc378b62c9a6feda647bad4719d2de7699","analyzedAt":"2026-08-16T09:01:53.433Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}