{"record":{"id":"f9e201911ccfe510","repo":"videojs/video.js","slug":"failed-to-execute-fnname-on-timeranges-the","errorCode":null,"errorMessage":"Failed to execute '${fnName}' on 'TimeRanges': The index provided (${index}) is non-numeric or out of bounds (0-${maxIndex}).","messagePattern":"Failed to execute '(.+?)' on 'TimeRanges': The index provided \\((.+?)\\) is non-numeric or out of bounds \\(0-(.+?)\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/utils/time.js","lineNumber":57,"sourceCode":"\n/**\n * Check if any of the time ranges are over the maximum index.\n *\n * @private\n * @param   {string} fnName\n *          The function name to use for logging\n *\n * @param   {number} index\n *          The index to check\n *\n * @param   {number} maxIndex\n *          The maximum possible index\n *\n * @throws  {Error} if the timeRanges provided are over the maxIndex\n */\nfunction rangeCheck(fnName, index, maxIndex) {\n  if (typeof index !== 'number' || index < 0 || index > maxIndex) {\n    throw new Error(`Failed to execute '${fnName}' on 'TimeRanges': The index provided (${index}) is non-numeric or out of bounds (0-${maxIndex}).`);\n  }\n}\n\n/**\n * Get the time for the specified index at the start or end\n * of a TimeRange object.\n *\n * @private\n * @param      {string} fnName\n *             The function name to use for logging\n *\n * @param      {string} valueIndex\n *             The property that should be used to get the time. should be\n *             'start' or 'end'\n *\n * @param      {Array} ranges\n *             An array of time ranges\n *","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/utils/time.js#L39-L75","documentation":"Thrown by the private rangeCheck helper guarding TimeRanges start(i)/end(i). It fires when the index is non-numeric, negative, or greater than length-1. This mirrors the native HTML5 TimeRanges spec error and is bound into every non-empty TimeRanges object returned by player.buffered/seekable/played.","triggerScenarios":"Calling player.buffered().start(5) when fewer ranges exist; passing a string index; an off-by-one loop (i <= length instead of i < length); calling start()/end() with no index on a non-empty object (the deprecated default of 0 is tolerated).","commonSituations":"Looping over buffered/seekable ranges without checking .length; assuming exactly one buffered range for progressive downloads; computing progress as buffered().end(length-1) on a live/HLS stream where ranges shift.","solutions":["Check timeRanges.length before indexing.","Iterate with for (let i = 0; i < ranges.length; i++).","Coalesce to a safe index: const idx = Math.min(i, ranges.length - 1)."],"exampleFix":"// before\nconst end = player.buffered().end(1);\n// after\nconst b = player.buffered();\nconst end = b.length >= 2 ? b.end(1) : (b.length === 1 ? b.end(0) : 0);","handlingStrategy":"validation","validationCode":"function rangeAt(ranges, fn, i = 0) {\n  if (typeof i !== 'number' || i < 0 || i >= ranges.length) {\n    throw new RangeError(`index ${i} out of bounds for length ${ranges.length}`);\n  }\n  return ranges[fn](i);\n}","typeGuard":"function isValidRangeIndex(ranges, i) {\n  return typeof i === 'number' && i >= 0 && i < ranges.length;\n}","tryCatchPattern":"try {\n  return ranges.start(i);\n} catch (err) {\n  if (/TimeRanges/.test(err.message) && /out of bounds|non-numeric/.test(err.message)) {\n    return ranges.length ? ranges.start(ranges.length - 1) : 0;\n  }\n  throw err;\n}","preventionTips":["Always check ranges.length before indexing start()/end().","Loop with for (let i = 0; i < ranges.length; i++), never i <= length.","Coerce string indices to Number and validate before passing."],"tags":["time-ranges","buffered","seekable","validation"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}