Skip to content

[BUG]: Violin calc density loop fails with tiny/near-equal spans - underrun ('undefined.v') or overrun (timeout) #7581

@Koookadooo

Description

@Koookadooo

Description

violin traces can fail or hang when y values contain high-precision floats that differ in precision.
This causes either:

  • Underrun: the internal KDE density array is not fully populated - "Cannot read properties of undefined (reading 'v')"
  • Overrun: the density loop runs one extra iteration - "TimeoutError".

Screenshots/Video

Image

Steps to reproduce

minimal reproduction:

Plotly.newPlot("myDiv", {
   "data":[
      {
         x: [0,0], y: [0.5006312999999999, 0.5006313],
         type:"violin"
      }
   ]
})

This code pen shows the in correct calculations happening for both cases (over run and underrun):

https://codepen.io/Koookadooo/pen/gbPxEVy?editors=0012

I have also attached a file of a python script showing both the "TimeoutError" and the "Cannot read properties of undefined (reading 'v')" using a larger set of high precision variable floating point numbers.

debug_html.py

To run:

  • Python debug_html.py
  • input 'y' to open files in browser to observe errors

Root Cause

src/traces/violin/calc.js currently generates KDE samples like this:

for (var k = 0, t = span[0]; t < (span[1] + step / 2); k++, t += step) {
    var v = kde(t);
    cdi.density[k] = {v: v, t: t};
    maxKDE = Math.max(maxKDE, v);
}

When step is extremely small (≈1e-14), repeated floating-point addition in t += step accumulates error:

  • In some spans, t exceeds span[1] + step/2 early → underrun (holes or shorter array).
  • In others, drift keeps t below the limit too long → overrun (extra sample).

Suggested fix

Instead, compute t fresh each iteration from the integer index k:

- for (var k = 0, t = span[0]; t < (span[1] + step / 2); k++, t += step) {
+ for (var k = 0; k < n; k++) {
+     var t = span[0] + k * step;
      var v = kde(t);
      cdi.density[k] = { v: v, t: t };
      maxKDE = Math.max(maxKDE, v);
}

Notes

Related: supercedes plotly/plotly.js#6490

That issue was closed as stale, but a maintainer noted that a PR would be welcome.

This report includes a confirmed repro and working fix.

I will be making a Pull Request next with the working fix referencing this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugsomething broken

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions