{"record":{"id":"4d217ab5f592e1fc","repo":"cube-js/cube","slug":"time-series-queries-without-daterange-aren-t-suppo","errorCode":null,"errorMessage":"Time series queries without dateRange aren't supported","messagePattern":"Time series queries without dateRange aren't supported","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/BaseQuery.js","lineNumber":1997,"sourceCode":"    const dateJoinCondition = cumulativeMeasure.dateJoinCondition();\n    const uniqDateJoinCondition = R.uniqBy(djc => djc[0].dimension, dateJoinCondition);\n    const cumulativeMeasures = [cumulativeMeasure];\n    if (!this.timeDimensions.find(d => d.granularity)) {\n      const filters = this.segments\n        .concat(this.filters)\n        .concat(this.dateFromStartToEndConditionSql(\n          // If the same time dimension is passed more than once, no need to build the same\n          // filter condition again and again. Different granularities don't play role here,\n          // as rollingWindow.granularity is used for filtering.\n          uniqDateJoinCondition,\n          fromRollup,\n          false\n        ));\n      return baseQueryFn(cumulativeMeasures, filters, false);\n    }\n\n    if (this.timeDimensions.filter(d => !d.dateRange && d.granularity).length > 0) {\n      throw new UserError('Time series queries without dateRange aren\\'t supported');\n    }\n\n    // We can't do meaningful query if few time dimensions with different ranges passed,\n    // it won't be possible to join them together without losing some rows.\n    const rangedTimeDimensions = this.timeDimensions.filter(d => d.dateRange && d.granularity);\n    const uniqTimeDimensionWithRanges = R.uniqBy(d => d.dateRange, rangedTimeDimensions);\n    if (uniqTimeDimensionWithRanges.length > 1) {\n      throw new Error('Can\\'t build query for time dimensions with different date ranges');\n    }\n\n    // We need to generate time series table for the lowest granularity among all time dimensions\n    const [dateSeriesDimension, dateSeriesGranularity] = this.timeDimensions.filter(d => d.granularity)\n      .reduce(([prevDim, prevGran], d) => {\n        const mg = this.minGranularity(prevGran, d.resolvedGranularity());\n        if (mg === d.resolvedGranularity()) {\n          return [d, mg];\n        }\n        return [prevDim, mg];","sourceCodeStart":1979,"sourceCodeEnd":2015,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js#L1979-L2015","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ntimeDimensions: [{ dimension: 'Orders.createdAt', granularity: 'day' }]\n// after\ntimeDimensions: [{ dimension: 'Orders.createdAt', granularity: 'day', dateRange: ['2024-01-01', '2024-01-31'] }]","handlingStrategy":"validation","validationCode":"function requireDateRangeForTimeSeries(query) {\n  const missing = (query.timeDimensions || []).filter(td => td.granularity && !td.dateRange);\n  if (missing.length) {\n    throw new Error(`timeDimensions with granularity need dateRange: ${missing.map(m => m.dimension).join(', ')}`);\n  }\n}","typeGuard":"const hasRange = (td) => Boolean(td && td.granularity && (Array.isArray(td.dateRange) || typeof td.dateRange === 'string'));","tryCatchPattern":"try {\n  return await cubeApi.load(query);\n} catch (e) {\n  if (/Time series queries without dateRange/.test(e.message)) {\n    // prompt user for a date range, then retry\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["time-dimensions","date-range","cumulative"],"backgroundTag":"time-series-missing-date-range","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}