{"record":{"id":"613d5bce2a252d81","repo":"plotly/plotly.js","slug":"c2dapply-axarray-and-valarray-must-be-the-same-le","errorCode":null,"errorMessage":"c2dApply: axArray and valArray must be the same length","messagePattern":"c2dApply: axArray and valArray must be the same length","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/components/fx/helpers.js","lineNumber":70,"sourceCode":" * for converting x/y values from calc space to data space. axArray and valArray are arrays\n * rather than single values because in the case of stacked subplots, there may be multiple axes\n * (and therefore multiple data values) corresponding to a single hover or click event.\n *\n * For linear and log axes, this conversion has no effect beyond validating the inputs.\n * However, for some axes types, the converted values may be of a different type than the\n * inputs:\n *  - For category axes, `c2d` converts calcdata values (numeric) into category labels (strings)\n *  - For date axes, `c2d` converts calcdata values (numeric values in ms) into date strings\n *\n * For axes which don't define `c2d` (e.g. geo, map), the inputs are passed through untouched.\n *\n * @param {Array} axArray : axes corresponding to each value in valArray\n * @param {Array} valArray : calcdata values\n * @return {Array} : data values, computed by calling `ax.c2d` (if defined) on each input value\n */\nexports.c2dApply = function (axArray, valArray) {\n    if(axArray.length !== valArray.length) {\n        Lib.warn('c2dApply: axArray and valArray must be the same length');\n    }\n    var out = new Array(valArray.length);\n    for (var i = 0; i < valArray.length; i++) {\n        var ax = axArray && axArray[i];\n        out[i] = ax && ax.c2d ? ax.c2d(valArray[i]) : valArray[i];\n    }\n    return out;\n};\n\nexports.getDistanceFunction = function (mode, dx, dy, dxy) {\n    if (mode === 'closest') return dxy || exports.quadrature(dx, dy);\n    return mode.charAt(0) === 'x' ? dx : dy;\n};\n\nexports.getClosest = function (cd, distfn, pointData) {\n    // do we already have a point number? (array mode only)\n    if (pointData.index !== false) {\n        if (pointData.index >= 0 && pointData.index < cd.length) {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/plotly/plotly.js/blob/1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314/src/components/fx/helpers.js#L52-L88","documentation":"c2dApply converts calcdata values to data values using each axis's c2d mapping; it requires one axis (or null) per value. When array lengths differ, it warns 'c2dApply: axArray and valArray must be the same length' and proceeds, using undefined for missing axes and returning raw values where no axis exists.","triggerScenarios":"Internal hover/zoom code calling exports.c2dApply with an axes array built from a different number of axes than the values array — e.g. multi-axis (xaxis/xaxis2) hover where one array was filtered or built per-subplot and the other wasn't.","commonSituations":"Custom code paths building axArray manually while reusing a valArray from another context; hover handlers over subplots where subplot arrays are spliced but value arrays are not; buggy plugins or forked plotly builds.","solutions":["Ensure axArray[i] corresponds to valArray[i]; rebuild axArray from the same loop that built valArray.","If an axis is legitimately unknown for a value, push null/undefined explicitly so lengths match by design.","Locate the caller (hover helpers) and check how axes arrays are constructed for multi-axis layouts.","Update plotly.js if triggered by stock hover code on a supported multi-axis layout — it may be a fixed regression.","As a workaround, avoid mixing axes arrays; process values per-axis in separate calls."],"exampleFix":"// before\nFx.c2dApply(xAxesOnly, xvals); // xAxesOnly.length < xvals.length after filtering\n// after\nconst axArray = xvals.map((_, i) => xAxes[i] || null);\nFx.c2dApply(axArray, xvals); // same length, nulls where no axis","handlingStrategy":"validation","validationCode":"function safeC2dApply(axArray, valArray) {\n  const ax = valArray.map((_, i) => (axArray && axArray[i]) || null);\n  return exports.c2dApply(ax, valArray);\n}","typeGuard":"function sameLength(a, b) {\n  return Array.isArray(a) && Array.isArray(b) && a.length === b.length;\n}","tryCatchPattern":"if (!sameLength(axArray, valArray)) {\n  console.error('c2dApply length mismatch', axArray.length, valArray.length);\n  return valArray; // pass through unconverted\n}\nreturn exports.c2dApply(axArray, valArray);","preventionTips":["Build axes arrays in the same loop as value arrays.","Push explicit nulls when a value has no axis so lengths stay aligned.","Unit-test multi-axis (x2y2) hover paths where arrays diverge most easily."],"tags":["hover","axes","array-length"],"backgroundTag":"array-length-mismatch","analyzedSha":"1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314","analyzedAt":"2026-09-02T22:03:39.906Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}