plotly/plotly.js · warning

Something went wrong during<this.id>fitbounds computations.

Error message

Something went wrong during<this.id>fitbounds computations.

What it means

When fitting the geo projection to the data bounds (layout.geo.fitbounds or fitbounds: 'geo'), plotly.js computes a scale factor from projection bounds; if that factor is not finite (division by zero from degenerate bounds), it warns 'Something went wrong during<id>fitbounds computations.' and skips the scale adjustment, leaving the projection at its previous state.

Source

Thrown at src/plots/geo/geo.js:328

    // scaleExtent uses fitScale so min/maxscale are relative to the
    // user-facing projection.scale (where 1 == fits lon/lat ranges).
    // https://d3js.org/d3-zoom#zoom_scaleExtent
    projection.scaleExtent = () => {
        const { minscale } = projLayout;
        const maxscale = projLayout.maxscale ?? Infinity;
        // swap if user supplied min > max so d3 receives a valid range
        return [s * Math.min(minscale, maxscale), s * Math.max(minscale, maxscale)];
    };

    if (geoLayout.fitbounds) {
        var b2 = projection.getBounds(makeRangeBox(axLon.range, axLat.range));
        var k2 = Math.min((b[1][0] - b[0][0]) / (b2[1][0] - b2[0][0]), (b[1][1] - b[0][1]) / (b2[1][1] - b2[0][1]));

        if (isFinite(k2)) {
            projection.scale(k2 * s);
        } else {
            Lib.warn('Something went wrong during' + this.id + 'fitbounds computations.');
        }
    } else {
        // adjust projection to user setting
        projection.scale(projLayout.scale * s);
    }

    // px coordinates of view mid-point,
    // useful to update `geo.center` after interactions
    var midPt = (this.midPt = [(b[0][0] + b[1][0]) / 2, (b[0][1] + b[1][1]) / 2]);

    projection.translate([t[0] + (midPt[0] - t[0]), t[1] + (midPt[1] - t[1])]).clipExtent(b);

    // the 'albers usa' projection does not expose a 'center' method
    // so here's this hack to make it respond to 'geoLayout.center'
    if (geoLayout._isAlbersUsa) {
        var centerPx = projection([center.lon, center.lat]);
        // If center isn't within the Albers USA bounds (clipped to the USA),
        // `projection(...)` returns null so skip the recentering

View on GitHub (pinned to 1d090e0b5f)

Solutions

  1. Check that the geo data actually spans a non-degenerate lon/lat extent before enabling fitbounds.
  2. Remove explicit range settings on axLon/axLat that collapse the bounds, and let fitbounds compute from full data.
  3. Fall back to manual projection.scale/center configuration instead of fitbounds for degenerate datasets.
  4. Validate/repair locations and coordinates (drop nulls, fix invalid ISO codes) so ranges are finite.

Example fix

// before
layout = {geo: {fitbounds: 'locations'}, /* data reduced to a single point */}
// after
// ensure >= 2 distinct points, or set manually:
layout = {geo: {projection: {scale: 3}, center: {lon: 10, lat: 50}}};
Defensive patterns

Strategy: fallback

Validate before calling

function hasNonDegenerateBounds(lon, lat) {
  const lonSet = new Set(lon.filter(Number.isFinite));
  const latSet = new Set(lat.filter(Number.isFinite));
  return lonSet.size > 1 && latSet.size > 1;
}
const layout = hasNonDegenerateBounds(lons, lats) ? {geo: {fitbounds: 'locations'}} : {geo: {projection: {scale: 2}}};

Type guard

const fitboundsSafe = (lons, lats) => lons.every(Number.isFinite) && lats.every(Number.isFinite) && new Set(lons).size > 1 && new Set(lats).size > 1;

Try / catch

try {
  Plotly.newPlot(gd, data, {geo: {fitbounds: 'locations'}});
} catch (e) {
  if (/fitbounds/.test(e.message)) {
    Plotly.newPlot(gd, data, {geo: {projection: {scale: 2}, center: {lon: 0, lat: 0}}});
  } else { throw e; }
}

Prevention

When it happens

Trigger: Enabling fitbounds on a geo subplot whose computed lon/lat ranges are degenerate (all points identical, empty data after filtering, or ranges producing zero-width/zero-height projection bounds so the scale ratio divides by zero).

Common situations: Fitting bounds to a single-point dataset; data filtered down to nothing; choropleth/geo traces with all locations invalid; fitbounds combined with manually set range that collapses to one point.


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