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

  1. Add an explicit dateRange to every time dimension that has a granularity.
  2. Use a relative date range string like 'last month' or ['2024-01-01','2024-06-30'] instead of omitting the range.
  3. If the dimension doesn't need series alignment, drop its granularity (dateRange-only filter).
  4. 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

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


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/4d217ab5f592e1fc. Report an issue: GitHub.