plotly/plotly.js · warning

Invalid color specifier: "${cstr}". Defaulting to "#000"

Error message

Invalid color specifier: "${cstr}". Defaulting to "#000"

What it means

plotly.js parses all color-like strings through culori-based `parse`. When the string cannot be converted to an RGB color, it warns 'Invalid color specifier' and falls back to black (#000). It exists because plotting silently using undefined colors is confusing; the warning points at the malformed input.

Source

Thrown at src/components/color/index.js:77

// 8-bit step first. Six decimals absorb the float error and still leave a
// genuine value such as 122.45 alone.
const snap01 = (v) => Math.round(v * 255e6) / 255e6;
const snap = (c) => ({ ...c, r: snap01(c.r), g: snap01(c.g), b: snap01(c.b) });

const formatRgb = (c) => culoriFormatRgb(snap(c));
const formatHex = (c) => culoriFormatHex(snap(c));

/**
 * Parse a color specifier string and return it as a culori rgb color object.
 *
 * @param {*} cstr - Color specifier
 * @param {Boolean} [silent] - Skip the warning, for callers that run per data point
 * @return {Object} A culori rgb color ({ mode: 'rgb', r: _, g: _, b: _, alpha: _ })
 */
const parse = (cstr, silent) => {
    const c = toColor(cstr);
    if (!c) {
        if (!silent && cstr != null) warn(`Invalid color specifier: "${cstr}". Defaulting to "#000"`);
        return BLACK;
    }
    // `toRgb` omits alpha when it's 1; make sure it's added since we expect it
    c.alpha ??= 1;

    return c;
};

// TODO: rename to `rgbString` to better describe return value
/**
 * Convert any color specifier to a normalized `rgb(r, g, b)` string.
 * Force alpha to 1 so that it gets dropped in the result.
 *
 * @param {*} cstr - Color specifier
 * @return {String}
 */
const rgb = (cstr) => formatRgb({ ...parse(cstr), alpha: 1 });

View on GitHub (pinned to 1d090e0b5f)

Solutions

  1. Log the cstr value in the warning and correct the offending data at its source.
  2. Use parse-silent-friendly inputs: hex (#rgb, #rrggbb, #rrggbbaa), rgb()/rgba()/hsl()/hsla() strings, or valid CSS named colors.
  3. Validate colors before assignment with a regex or the browser (e.g. assigning to a temporary element's style.color and comparing).
  4. Use a colorscale object/array for per-point coloring instead of raw strings from data.
  5. Guard optional attributes: only set color when the value is a non-empty string.

Example fix

// before
Plotly.restyle(gd, 'marker.color', trace.color || 'auto'); // 'auto' is invalid
// after
const color = /^#([0-9a-f]{3,8})$/i.test(trace.color || '') ? trace.color : '#000000';
Plotly.restyle(gd, 'marker.color', color);
Defensive patterns

Strategy: validation

Validate before calling

function isValidColor(c) {
  if (typeof c !== 'string') return false;
  const s = new Option().style;
  s.color = '';
  s.color = c;
  return s.color !== '';
}

Type guard

function isColorString(v) {
  return typeof v === 'string' && isValidColor(v);
}

Try / catch

// plotly only warns (no throw), so prefer pre-validation
if (!isValidColor(color)) {
  console.warn('rejecting bad color', color);
  color = '#000000';
}
Plotly.restyle(gd, 'marker.color', color);

Prevention

When it happens

Trigger: Setting any color attribute (marker.color, line.color, layout colorway, font color, colorscale stop values) to a string culori cannot parse — e.g. 'not-a-color', a misspelled keyword ('rebeccapurplee'), an out-of-gamut CSS4 color, an rgba() string with the wrong argument count, or a number where a string is expected.

Common situations: Colors coming from user data or API responses that were assumed valid; typos in CSS color names; using 'rgb(r,g,b)' with percentages mixed with numbers; passing a hex string missing the '#' or with 5 digits.

Related errors


AI-assisted analysis of plotly/plotly.js@1d090e0b5f (2026-09-02). Data as JSON: /api/errors/c8f6866e01c987e4. Report an issue: GitHub.