juspay/hyperswitch · error
Invalid color value
Error message
Invalid color value
What it means
Thrown by toRgbArray() in the vendored invert-color code inside the payment link status page. It triggers when the colour passed to invert() is falsy (null, undefined, empty string), before hex parsing happens. On this page the colour comes from the status payload's theme / payment_button_colour fields used for re-rendering branded UI.
Source
Thrown at crates/router/src/core/payment_link/payment_link_status/status.js:40
len = 2;
}
return (new Array(len).join("0") + str).slice(-len);
}
function hexToRgbArray(hex) {
if (hex.slice(0, 1) === "#") hex = hex.slice(1);
var RE_HEX = /^(?:[0-9a-f]{3}){1,2}$/i;
if (!RE_HEX.test(hex)) throw new Error('Invalid HEX color: "' + hex + '"');
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
return [
parseInt(hex.slice(0, 2), 16),
parseInt(hex.slice(2, 4), 16),
parseInt(hex.slice(4, 6), 16),
];
}
function toRgbArray(c) {
if (!c) throw new Error("Invalid color value");
if (Array.isArray(c)) return c;
return typeof c === "string" ? hexToRgbArray(c) : [c.r, c.g, c.b];
}
function getLuminance(c) {
var i, x;
var a = [];
for (i = 0; i < c.length; i++) {
x = c[i] / 255;
a[i] = x <= 0.03928 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
}
function invertToBW(color, bw, asArr) {
var DEFAULT_BW = {
black: "#090302",
white: "#FFFFFC",
threshold: Math.sqrt(1.05 * 0.05) - 0.05,
};View on GitHub (pinned to 9b8b89dc37)
Solutions
- Default the colour before calling invert(): var primaryColor = theme || '#1a2b3c';
- Make the status API always include a non-empty theme (server-side default)
- Backfill or correct payment link rows whose theme is NULL/empty
Example fix
// before var contrastBWColor = invert(primaryColor, true); // after var primaryColor = paymentDetails.theme || '#1a2b3c'; var contrastBWColor = invert(primaryColor, true);
Defensive patterns
Strategy: type-guard
Validate before calling
// Before status-page colour setup
if (!paymentDetails.theme) {
paymentDetails.theme = '#1a2b3c';
} Type guard
/** @param {unknown} c @returns {c is string} */
function isUsableColor(c) {
return typeof c === 'string' && c.length > 0;
} Try / catch
try {
contrastBWColor = invert(theme, true);
} catch (e) {
if (e.message === 'Invalid color value') {
contrastBWColor = '#ffffff';
} else {
throw e;
}
} Prevention
- Server-side: always include a non-empty theme in status responses
- Backfill legacy payment link rows with NULL themes
- Guard the falsy case separately from the malformed-hex case when triaging
When it happens
Trigger: Status page render where the branding colour fields are missing, null, or '' in the payment link status response — for example a link created with no theme configured at all.
Common situations: Links created before branding fields existed (legacy rows with NULL theme); status payloads assembled by a different code path that omits branding; a default theme applied on the initiate page but forgotten on the status page.
Related errors
AI-assisted analysis of juspay/hyperswitch@9b8b89dc37 (2026-08-16).
Data as JSON: /api/errors/64a7644289acbabe.
Report an issue: GitHub.