cube-js/cube · error · UserError
Time series queries without dateRange aren't supported
Error message
Time series queries without dateRange aren't supported
What it means
overTimeSeriesQuery builds a time-series table (date spine) to join cumulative results against, which requires a bounded range. If any time dimension has a granularity but no dateRange, Cube cannot generate the series and throws this UserError.
Source
Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:1997
const dateJoinCondition = cumulativeMeasure.dateJoinCondition();
const uniqDateJoinCondition = R.uniqBy(djc => djc[0].dimension, dateJoinCondition);
const cumulativeMeasures = [cumulativeMeasure];
if (!this.timeDimensions.find(d => d.granularity)) {
const filters = this.segments
.concat(this.filters)
.concat(this.dateFromStartToEndConditionSql(
// If the same time dimension is passed more than once, no need to build the same
// filter condition again and again. Different granularities don't play role here,
// as rollingWindow.granularity is used for filtering.
uniqDateJoinCondition,
fromRollup,
false
));
return baseQueryFn(cumulativeMeasures, filters, false);
}
if (this.timeDimensions.filter(d => !d.dateRange && d.granularity).length > 0) {
throw new UserError('Time series queries without dateRange aren\'t supported');
}
// We can't do meaningful query if few time dimensions with different ranges passed,
// it won't be possible to join them together without losing some rows.
const rangedTimeDimensions = this.timeDimensions.filter(d => d.dateRange && d.granularity);
const uniqTimeDimensionWithRanges = R.uniqBy(d => d.dateRange, rangedTimeDimensions);
if (uniqTimeDimensionWithRanges.length > 1) {
throw new Error('Can\'t build query for time dimensions with different date ranges');
}
// We need to generate time series table for the lowest granularity among all time dimensions
const [dateSeriesDimension, dateSeriesGranularity] = this.timeDimensions.filter(d => d.granularity)
.reduce(([prevDim, prevGran], d) => {
const mg = this.minGranularity(prevGran, d.resolvedGranularity());
if (mg === d.resolvedGranularity()) {
return [d, mg];
}
return [prevDim, mg];View on GitHub (pinned to 7d981676b3)
Solutions
- Add an explicit dateRange to every time dimension that has a granularity.
- Use a relative date range string like 'last month' or ['2024-01-01','2024-06-30'] instead of omitting the range.
- If the dimension doesn't need series alignment, drop its granularity (dateRange-only filter).
- Catch UserError client-side and prompt the user to select a date range before running cumulative queries.
Example fix
// before
timeDimensions: [{ dimension: 'Orders.createdAt', granularity: 'day' }]
// after
timeDimensions: [{ dimension: 'Orders.createdAt', granularity: 'day', dateRange: ['2024-01-01', '2024-01-31'] }] Defensive patterns
Strategy: validation
Validate before calling
function requireDateRangeForTimeSeries(query) {
const missing = (query.timeDimensions || []).filter(td => td.granularity && !td.dateRange);
if (missing.length) {
throw new Error(`timeDimensions with granularity need dateRange: ${missing.map(m => m.dimension).join(', ')}`);
}
} Type guard
const hasRange = (td) => Boolean(td && td.granularity && (Array.isArray(td.dateRange) || typeof td.dateRange === 'string'));
Try / catch
try {
return await cubeApi.load(query);
} catch (e) {
if (/Time series queries without dateRange/.test(e.message)) {
// prompt user for a date range, then retry
}
throw e;
} Prevention
- Always set dateRange when using cumulative/rolling measures
- Validate query objects client-side before sending to the API
- Default date ranges in UI chart builders for time series
When it happens
Trigger: Submitting a query where timeDimensions contains { dimension, granularity } but no dateRange while the query requires time-series generation (rolling/cumulative measures, overTimeSeries paths) — e.g. rollingWindow or cumulative measures without dateRange.
Common situations: Dashboards sending cumulative queries with only 'last month' style relative ranges omitted, API clients forgetting dateRange, or frontend chart builders passing granularity-only time dimensions.
Related errors
- Can't build query for time dimensions with different date ra
- compareDateRange can only exist for one timeDimension
- Pre-aggregation '${this.preAggregation.tableName}' requested
- Date range expected to be an array with 2 elements but ${ran
- Date range expected to be a string array but ${range} found
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/4d217ab5f592e1fc.
Report an issue: GitHub.