{"record":{"id":"d596f0f9736ac725","repo":"chartjs/Chart.js","slug":"min-and-max-are-too-far-apart-with-stepsize","errorCode":null,"errorMessage":"${min} and ${max} are too far apart with stepSize of ${stepSize} ${minor}","messagePattern":"(.+?) and (.+?) are too far apart with stepSize of (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scales/scale.time.js","lineNumber":475,"sourceCode":"    const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));\n    const stepSize = valueOrDefault(options.ticks.stepSize, 1);\n    const weekday = minor === 'week' ? timeOpts.isoWeekday : false;\n    const hasWeekday = isNumber(weekday) || weekday === true;\n    const ticks = {};\n    let first = min;\n    let time, count;\n\n    // For 'week' unit, handle the first day of week option\n    if (hasWeekday) {\n      first = +adapter.startOf(first, 'isoWeek', weekday);\n    }\n\n    // Align first ticks on unit\n    first = +adapter.startOf(first, hasWeekday ? 'day' : minor);\n\n    // Prevent browser from freezing in case user options request millions of milliseconds\n    if (adapter.diff(max, min, minor) > 100000 * stepSize) {\n      throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor);\n    }\n\n    const timestamps = options.ticks.source === 'data' && this.getDataTimestamps();\n    for (time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++) {\n      addTick(ticks, time, timestamps);\n    }\n\n    if (time === max || options.bounds === 'ticks' || count === 1) {\n      addTick(ticks, time, timestamps);\n    }\n\n    // @ts-ignore\n    return Object.keys(ticks).sort(sorter).map(x => +x);\n  }\n\n  /**\n\t * @param {number} value\n\t * @return {string}","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/chartjs/Chart.js/blob/cb02e1d207bd4c4c40b20c259017f85f26f1e30a/src/scales/scale.time.js#L457-L493","documentation":"TimeScale._generate() builds ticks by stepping from min to max in increments of stepSize on the minor unit using adapter.add. To prevent the browser from freezing when options would produce millions of ticks, it caps the span at adapter.diff(max, min, minor) > 100000 * stepSize and throws, reporting the min, max, stepSize, and unit. This is a deliberate guard against pathological time-axis configurations.","triggerScenarios":"A very wide data range (e.g. years of millisecond data) combined with a small time.unit and a small ticks.stepSize (default stepSize = 1), so 100000*stepSize ticks would be generated; explicitly setting ticks.stepSize to a tiny number on a multi-year range; unit auto-picking a fine unit (millisecond/second) on a huge range.","commonSituations":"Plotting a time series spanning years with stepSize left at default 1; data with one outlier timestamp far in the future/past stretching min/max; misconfigured ticks.stepSize in seconds over a multi-year dataset; mixing units where time.unit is forced to a small value.","solutions":["Increase ticks.stepSize so that (max-min)/stepSize stays well under 100000 (e.g. set stepSize: 7 with unit 'day' for weekly ticks over years).","Set an explicit, coarser time.unit (e.g. 'month' or 'year') so each step covers more time.","Filter/clamp outlier timestamps so min and max reflect the real data window.","Set time.min/time.max to bound the visible range, reducing adapter.diff(max, min, minor)."],"exampleFix":"// before\noptions: {\n  scales: { x: { type: 'time', time: { unit: 'second' } } }\n} // years of data, stepSize defaults to 1 -> throws\n\n// after\noptions: {\n  scales: { x: { type: 'time', time: { unit: 'week' }, ticks: { stepSize: 1 } } }\n}","handlingStrategy":"validation","validationCode":"// Estimate the tick count and refuse configs that would exceed Chart.js' guard.\nfunction validateTimeRange(minMs, maxMs, unit, stepSize) {\n  const msPerUnit = {\n    millisecond: 1, second: 1000, minute: 60000, hour: 3600000,\n    day: 86400000, week: 604800000, month: 2592000000, year: 31536000000\n  };\n  const per = msPerUnit[unit] || 1;\n  const steps = (maxMs - minMs) / (per * (stepSize || 1));\n  if (steps > 100000) {\n    throw new Error(\n      `Time range too large: ~${Math.round(steps)} ticks. Increase ticks.stepSize or use a coarser time.unit.`\n    );\n  }\n}\nvalidateTimeRange(minTimestamp, maxTimestamp, 'second', 1);","typeGuard":null,"tryCatchPattern":"// Catch the guard during development and surface a clearer config message.\ntry {\n  chart.update();\n} catch (e) {\n  if (/too far apart/i.test(String(e?.message))) {\n    console.error('Time axis span too large for current stepSize/unit. Coarsen time.unit or raise ticks.stepSize.', e.message);\n  } else throw e;\n}","preventionTips":["Set an explicit time.unit and ticks.stepSize matched to the data span.","Filter/clamp outlier timestamps so min/max reflect the real window.","Bound the visible range with time.min/time.max.","Compute (max-min)/(stepSize*unitMs) and keep it well under 100000."],"tags":["time-scale","ticks","configuration","performance","data"],"backgroundTag":null,"analyzedSha":"cb02e1d207bd4c4c40b20c259017f85f26f1e30a","analyzedAt":"2026-08-12T23:38:10.965Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}