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

  1. Default the colour before calling invert(): var primaryColor = theme || '#1a2b3c';
  2. Make the status API always include a non-empty theme (server-side default)
  3. 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

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.