framework7io/framework7 · error · Error

unexpected hex ${hex}

Error message

unexpected hex ${hex}

What it means

`argbFromHex` converts a CSS-style hex string to an ARGB integer, accepting only 3, 6, or 8 hex digits (after stripping '#'). Any other length or non-hex shape triggers `throw new Error('unexpected hex ' + hex)`. It's an input-format guard so downstream parseIntHex parsing never sees malformed data.

Source

Thrown at src/core/shared/material-color-utils.js:2709

      sourceColorHct: sourceColorHct,
      variant: Variant.VIBRANT,
      contrastLevel: contrastLevel,
      isDark: isDark,
      platform: platform,
      specVersion: specVersion
    });
  }
}

function hexFromArgb(argb) {
  const r = redFromArgb(argb), g = greenFromArgb(argb), b = blueFromArgb(argb), outParts = [ r.toString(16), g.toString(16), b.toString(16) ];
  for (const [i, part] of outParts.entries()) 1 === part.length && (outParts[i] = "0" + part);
  return "#" + outParts.join("");
}

function argbFromHex(hex) {
  const isThree = 3 === (hex = hex.replace("#", "")).length, isSix = 6 === hex.length, isEight = 8 === hex.length;
  if (!isThree && !isSix && !isEight) throw new Error("unexpected hex " + hex);
  let r = 0, g = 0, b = 0;
  return isThree ? (r = parseIntHex(hex.slice(0, 1).repeat(2)), g = parseIntHex(hex.slice(1, 2).repeat(2)), 
  b = parseIntHex(hex.slice(2, 3).repeat(2))) : isSix ? (r = parseIntHex(hex.slice(0, 2)), 
  g = parseIntHex(hex.slice(2, 4)), b = parseIntHex(hex.slice(4, 6))) : isEight && (r = parseIntHex(hex.slice(2, 4)), 
  g = parseIntHex(hex.slice(4, 6)), b = parseIntHex(hex.slice(6, 8))), (255 << 24 | (255 & r) << 16 | (255 & g) << 8 | 255 & b) >>> 0;
}

function parseIntHex(value) {
  return parseInt(value, 16);
}

export { Hct, SchemeMonochrome, SchemeTonalSpot, SchemeVibrant, argbFromHex, hexFromArgb };

View on GitHub (pinned to 6557591266)

Solutions

  1. Normalize the input before calling: trim, strip '#', reject '0x' prefix, and ensure length is 3, 6, or 8.
  2. Convert 4- or 8-digit hex with alpha explicitly (expand #RGBA to #RGB, keep 8-digit as RRGGBBAA).
  3. Parse rgb()/hsl() strings with a dedicated parser instead of feeding them to argbFromHex.
  4. Validate with a regex like /^#?([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i before the call.

Example fix

// before
argbFromHex(color); // color = '#FFAA' (4-digit) -> throws
// after
if (!/^#?([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color)) color = '#000000';
const argb = argbFromHex(color);
Defensive patterns

Strategy: validation

Validate before calling

const HEX_RE = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
if (!HEX_RE.test(hex)) throw new TypeError(`argbFromHex expects 3/6/8-digit hex, got: ${hex}`);
const argb = argbFromHex(hex);

Type guard

function isParseableHex(s) {
  return typeof s === 'string' && /^#?([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(s.trim());
}

Try / catch

let argb;
try {
  argb = argbFromHex(input);
} catch (e) {
  if (e.message.startsWith('unexpected hex')) {
    console.warn('Bad hex color, using fallback', input);
    argb = argbFromHex('#000000');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `argbFromHex(hex)` with a string whose length is not 3/6/8 after removing '#': e.g. 4-digit #RGBA, 12-digit values, empty strings, rgb() strings, or hex values containing '0x' prefixes.

Common situations: Pasting colors from design tools that emit #RRGGBBAA shortened forms or uppercase '0X' prefixes; user-typed colors in a color picker config; reading colors from APIs that return rgb()/hsl() strings.


AI-assisted analysis of framework7io/framework7@6557591266 (2026-09-02). Data as JSON: /api/errors/0a4bef46f68e1e93. Report an issue: GitHub.