videojs/video.js · error · Error
This TimeRanges object is empty
Error message
This TimeRanges object is empty
What it means
Thrown by the start() method on a TimeRanges object created empty (ranges undefined or length 0). createTimeRangesObj installs start/end stubs that throw immediately to signal there is no range data, rather than returning undefined. Represents a player state with no buffered/seekable/played data.
Source
Thrown at src/js/utils/time.js:106
}
/**
* Create a time range object given ranges of time.
*
* @private
* @param {Array} [ranges]
* An array of time ranges.
*
* @return {TimeRange}
*/
function createTimeRangesObj(ranges) {
let timeRangesObj;
if (ranges === undefined || ranges.length === 0) {
timeRangesObj = {
length: 0,
start() {
throw new Error('This TimeRanges object is empty');
},
end() {
throw new Error('This TimeRanges object is empty');
}
};
} else {
timeRangesObj = {
length: ranges.length,
start: getRange.bind(null, 'start', 0, ranges),
end: getRange.bind(null, 'end', 1, ranges)
};
}
if (window.Symbol && window.Symbol.iterator) {
timeRangesObj[window.Symbol.iterator] = () => (ranges || []).values();
}
return timeRangesObj;View on GitHub (pinned to c3a7e0e6d2)
Solutions
- Guard with if (ranges.length > 0) before calling start()/end().
- Wait for 'progress' or 'loadedmetadata' events before reading buffered/seekable.
- Coalesce to 0: const s = buf.length ? buf.start(buf.length - 1) : 0.
Example fix
// before const start = player.buffered().start(0); // after const b = player.buffered(); const start = b.length ? b.start(0) : 0;
Defensive patterns
Strategy: validation
Validate before calling
function safeStart(ranges) {
return ranges.length ? ranges.start(0) : 0;
} Type guard
function hasRanges(ranges) {
return ranges && ranges.length > 0;
} Try / catch
try {
return ranges.start(0);
} catch (err) {
if (/TimeRanges object is empty/.test(err.message)) return 0;
throw err;
} Prevention
- Guard every start() call with if (ranges.length).
- Wait for 'progress'/'loadedmetadata' before reading buffered/seekable.
- Default to 0 when the object is empty rather than letting it throw.
When it happens
Trigger: Calling player.buffered().start(0) before any media data has buffered; reading start() immediately after a source change or a flush that clears ranges; on live streams before a seekable window is established.
Common situations: Reading buffered progress at 'ready' or synchronously after src() before 'loadedmetadata'/'progress' fire; HLS/DASH streams with no buffered ranges yet; calling end() to draw a progress bar before playback begins.
Related errors
- Failed to execute '${fnName}' on 'TimeRanges': The index pro
- currentDimension only accepts width or height value
- Illegal component name, "${name}"; must be a non-empty strin
- Illegal component, "${name}"; ${reason}.
- Invalid target for ${objName(obj)}#${fnName}; must be a DOM
AI-assisted analysis of videojs/video.js@c3a7e0e6d2 (2026-08-13).
Data as JSON: /api/errors/bd6d3ed04181373a.
Report an issue: GitHub.