plotly/plotly.js · info

encountered bad format: "${key}"

Error message

encountered bad format: "${key}"

What it means

lib.warnBadFormat warns 'encountered bad format: "<f>"' the first time a formatting function/string that isn't a recognized d3-format specifier is used in tick/tickformat or hover template value formatting; repeats are suppressed via seenBadFormats. After warning, the value falls back to a plain String conversion (noFormat).

Source

Thrown at src/lib/index.js:41

    // that prefix before deciding whether to trim, and reattach it: prepending
    // the tilde to the whole string (e.g. "~+.2f") is an invalid spec that
    // d3Format rejects, so "+.2f" used to be silently dropped.
    var prefix = (formatStr.match(/^[+\-( ]?/) || [''])[0];
    var rest = formatStr.slice(prefix.length);

    // try adding tilde to trim trailing zeros; leave symbol-led specs ($, #)
    // untrimmed, since the symbol isn't part of the prefix we stripped above
    if (!/^[~,.0$#]/.test(rest) && /[&fps]/.test(rest)) return prefix + '~' + rest;

    return formatStr;
};

var seenBadFormats = {};
lib.warnBadFormat = function (f) {
    var key = String(f);
    if (!seenBadFormats[key]) {
        seenBadFormats[key] = 1;
        lib.warn('encountered bad format: "' + key + '"');
    }
};

lib.noFormat = function (value) {
    return String(value);
};

lib.numberFormat = function (formatStr) {
    var fn;
    try {
        fn = d3Format(lib.adjustFormat(formatStr));
    } catch (e) {
        lib.warnBadFormat(formatStr);
        return lib.noFormat;
    }

    return fn;
};

View on GitHub (pinned to 1d090e0b5f)

Solutions

  1. Replace the format string with valid d3-format syntax for numbers (e.g. ',.2f', '.0%', '$,.0f').
  2. For dates, use d3 time-format syntax via layout's tickformat with codes like '%Y-%m-%d' only inside valid specifier context, or set tickformatstops with proper d3.time.format values where applicable.
  3. Check that the value at the warning site is what you intended — the suppressed repeat means you'll only see the first occurrence.
  4. Strip strftime-style '%' date patterns or convert them explicitly before assignment.
  5. Test formatting on a minimal figure to isolate which attribute carries the bad format.

Example fix

// before
layout: {yaxis: {tickformat: '0.00x'}} // invalid d3 format
// after
layout: {yaxis: {tickformat: '.2%'}}
Defensive patterns

Strategy: validation

Validate before calling

function isValidD3Format(f) {
  try {
    require('d3-format').format(f);
    return true;
  } catch (e) {
    return false;
  }
}
axis.tickformat = isValidD3Format(requested) ? requested : ',.2f';

Type guard

function isFormatSpecifier(v) {
  return typeof v === 'string' && /^[-+ #(0]*[0-9]*(\.[0-9]+)?[~s%eEfgGnpqoxXbBcdjZ]+$/.test(v.trim());
}

Try / catch

if (!isFormatSpecifier(cfg.tickformat)) {
  console.warn('replacing bad tickformat', cfg.tickformat);
  cfg.tickformat = ',.2f';
}

Prevention

When it happens

Trigger: Setting tickformat, hoverformat, or a text/template formatting value to something d3-format rejects — e.g. tickformat: '%s' (strftime-style instead of d3), '0.00x', an empty string used where a format was expected, or passing a custom object as a formatter.

Common situations: Migrating from matplotlib/strftime habits ('%Y-%m-%d') into d3-format syntax ('%Y-%m-%d' is invalid; d3 uses ~%Y-%m-%d or the d3 time format object); typos like '0.0%' misspelled; generating tickformat strings from user config.


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