cube-js/cube · error

Granularity "${timeDimension.granularity}" not found in time

Error message

Granularity "${timeDimension.granularity}" not found in time dimension "${timeDimension.dimension}"

What it means

ResultSet.timeSeries() builds the x-axis date buckets for a time-series result. When a time dimension uses a custom granularity defined in the data model viagranularities annotations, the resultset annotation must contain an entry named `dimension.granularity`. This error is thrown when the requested granularity is neither a built-in interval nor present in the annotations, so no series can be generated.

Source

Thrown at packages/cubejs-client-core/src/ResultSet.ts:488

    if (!dateRange) {
      return null;
    }

    const padToDay = timeDimension.dateRange ?
      (timeDimension.dateRange as string[]).find(d => d.match(DateRegex)) :
      !['hour', 'minute', 'second'].includes(timeDimension.granularity);

    const [start, end] = dateRange;
    const range = dayRange(start, end, annotations);

    if (isPredefinedGranularity(timeDimension.granularity)) {
      return TIME_SERIES[timeDimension.granularity](
        padToDay ? range.snapTo('d') : range
      );
    }

    if (!annotations?.[`${timeDimension.dimension}.${timeDimension.granularity}`]) {
      throw new Error(`Granularity "${timeDimension.granularity}" not found in time dimension "${timeDimension.dimension}"`);
    }

    return timeSeriesFromCustomInterval(
      start, end, annotations[`${timeDimension.dimension}.${timeDimension.granularity}`].granularity!
    );
  }

  /**
   * Base method for pivoting [ResultSet](#result-set) data.
   * Most of the time shouldn't be used directly and [chartPivot](#result-set-chart-pivot)
   * or [tablePivot](#table-pivot) should be used instead.
   *
   * You can find the examples of using the `pivotConfig` [here](#types-pivot-config)
   * ```js
   * // For query
   * {
   *   measures: ['Stories.count'],
   *   timeDimensions: [{

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the granularity name in the query timeDimensions exactly matches a granularity name declared in the cube's granularities (or a builtin: day/week/month/quarter/year/hour/minute/second)
  2. Inspect resultSet.loadResponses[0].annotation for a key `<dimension>.<granularity>`; if missing, ensure the backend returns full annotations (check proxy/caching code that may strip annotation)
  3. Update @cubejs-client/core to a version supporting custom granularities and confirm the backend supports them
  4. As a fallback, use built-in granularities or build the series manually from rawData()

Example fix

// before
granularity: 'Qtr' // typo, not defined in the cube
// after
// cube schema
dimension XYZ { timeDimension { granularities: [quarter, quarterOfDay] } }
// query
granularity: 'quarterOfDay' // must match the schema-declared name and appear in annotations
Defensive patterns

Strategy: validation

Validate before calling

function canBuildTimeSeries(resultSet) {
  const td = resultSet.loadResponse?.query?.timeDimensions?.[0];
  if (!td || !td.granularity) return true; // builtin path
  const key = `${td.dimension}.${td.granularity}`;
  return Boolean(resultSet.loadResponse?.annotation?.[key]);
}
if (!canBuildTimeSeries(rs)) { console.warn('custom granularity missing from annotations', td); return; }

Type guard

function hasGranularityAnnotation(rs: ResultSet): boolean {
  const td = rs.loadResponse?.query?.timeDimensions?.[0];
  if (!td?.granularity) return true;
  return rs.loadResponse?.annotation?.[`${td.dimension}.${td.granularity}`] != null;
}

Try / catch

let series;
try { series = rs.seriesNames(); } catch (e) {
  if (String(e?.message).includes('not found in time dimension')) {
    series = []; // render empty chart and surface schema/query mismatch
  } else throw e;
}

Prevention

When it happens

Trigger: Calling chart-generating methods (seriesNumericColumns/series → timeSeries) on a ResultSet whose query used a timeDimension with a custom (non-builtin) granularity while the loadResponse annotation lacks a `<dimension>.<granularity>` key — e.g. annotation omitted, annotation stripped by a proxy, or a typo/mismatch between the granularity name in the query and the granularity name declared in the data model's granularities list.

Common situations: Custom granularities declared in the cube schema (e.g. granularities: [{name:'quarter_hour'}]) but queried with a different casing/spelling; caching or mock loadResponses built without annotations; backend versions older than custom-granularity support returning annotations without granularity entries; passing a ResultSet produced by decompose/comparison handling where the wrong sub-result's annotations are consulted.

Related errors


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