cube-js/cube · error · Error
The count of generated date ranges (${count}) for the reques
Error message
The count of generated date ranges (${count}) for the request from [${startStr}] to [${endStr}] by ${intervalStr} is over limit (${limit}). Please reduce the requested date interval or use bigger granularity. What it means
checkSeriesForDateRange (packages/cubejs-backend-shared/src/time.ts:209) computes the number of interval buckets the requested [start,end] range produces (rangeSeconds / intervalAsSeconds) and throws if it exceeds a hard soft limit of 50000. It guards timeSeries/timeSeriesFromCustomInterval against generating enormous arrays of date ranges that would exhaust memory or stall the request.
Source
Thrown at packages/cubejs-backend-shared/src/time.ts:209
Object.entries(parsedInterval).forEach(([key, value]) => {
duration.add(value, key as unitOfTime.DurationConstructor);
});
return duration;
};
function checkSeriesForDateRange(intervalStr: string, [startStr, endStr]: QueryDateRange): void {
const intervalParsed = parseSqlInterval(intervalStr);
const intervalAsSeconds = parsedSqlIntervalToDuration(intervalParsed).asSeconds();
const start = moment(startStr);
const end = moment(endStr);
const rangeSeconds = end.diff(start, 'seconds');
const limit = 50000; // TODO Make this as configurable soft limit
const count = rangeSeconds / intervalAsSeconds;
if (count > limit) {
throw new Error(`The count of generated date ranges (${count}) for the request from [${startStr}] to [${endStr}] by ${intervalStr} is over limit (${limit}). Please reduce the requested date interval or use bigger granularity.`);
}
}
export const timeSeriesFromCustomInterval = (intervalStr: string, [startStr, endStr]: QueryDateRange, origin: moment.Moment, options: TimeSeriesOptions = { timestampPrecision: 3 }): QueryDateRange[] => {
checkSeriesForDateRange(intervalStr, [startStr, endStr]);
const intervalParsed = parseSqlInterval(intervalStr);
const start = moment(startStr);
const end = moment(endStr);
let alignedStart = alignToOrigin(start, intervalParsed, origin);
const dates: QueryDateRange[] = [];
while (alignedStart.isBefore(end)) {
const s = alignedStart.clone();
alignedStart = addInterval(alignedStart, intervalParsed);
dates.push([
s.format(`YYYY-MM-DDTHH:mm:ss.${'0'.repeat(options.timestampPrecision)}`),View on GitHub (pinned to 7d981676b3)
Solutions
- Reduce the requested date range (narrow start/end) so the bucket count stays under 50000.
- Use a bigger granularity (minute/hour/day instead of second) — as the message itself suggests.
- Clamp or round user-supplied ranges in application code before calling timeSeries.
- Pre-aggregate upstream (e.g. rollups) and query the coarser series instead.
Example fix
// before
timeSeries('second', ['2020-01-01', '2026-01-01']); // ~190M buckets: throws
// after
timeSeries('hour', ['2020-01-01', '2026-01-01']); // ~52k → use 'day' to stay safe
timeSeries('day', ['2020-01-01', '2026-01-01']); Defensive patterns
Strategy: validation
Validate before calling
const MAX = 50000;
function assertSeriesSize(interval: string, [start, end]: [string, string]) {
const seconds = (Date.parse(end) - Date.parse(start)) / 1000;
const intervalSeconds = /* parse '1 second' etc. */ 1;
if (seconds / intervalSeconds > MAX) {
throw new Error(`Requested series has >${MAX} buckets; narrow the range or increase granularity`);
}
} Try / catch
try {
return timeSeries(granularity, range, opts);
} catch (e) {
if (/is over limit/.test(String(e))) {
return timeSeries('day', range, opts); // coarser fallback
}
throw e;
} Prevention
- Clamp user-supplied date pickers to a maximum span per granularity
- Default dashboards to day/hour granularity, not second
- Compute bucket count client-side before requesting
- Pre-aggregate long histories into rollups
When it happens
Trigger: Calling timeSeries(granularity, ['2000-01-01','2026-01-01']) with a small granularity such as 'second' or 'minute' over many years, or timeSeriesFromCustomInterval('1 second', ...) over a multi-month span, so count = rangeSeconds/intervalAsSeconds > 50000.
Common situations: Dashboard widgets requesting second-level granularity over years of history; user-supplied date pickers allowing arbitrarily wide ranges combined with fine granularity; misconfigured custom intervals like '1 millisecond'.
Related errors
- Unsupported time granularity: ${granularity}
- options.timestampPrecision is required, actual: ${options.ti
- Unknown timezone: ${timezone}
- Time series queries without dateRange aren't supported
- Can't parse date: '${from}'
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/703730708698e7f5.
Report an issue: GitHub.