cube-js/cube · error · UserError

Query should contain either measures, dimensions or timeDime

Error message

Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid

What it means

Semantic validation in normalizeQuery: after schema validation passes, the query is rejected because it contains no measures, no dimensions, and no timeDimensions with granularities — i.e. nothing to select, so it cannot produce a valid result set.

Source

Thrown at packages/cubejs-api-gateway/src/query.js:447

 * @param {Query} query
 * @param {boolean} persistent
 * @param {CacheMode} [cacheMode]
 * @throws {UserError}
 * @returns {import('./types/query').NormalizedQuery}
 */
const normalizeQuery = (query, persistent, cacheMode) => {
  query = normalizeQueryCacheMode(query, cacheMode);
  query.timezone = query.timezone || getEnv('defaultTimezone');
  const { error, value } = querySchema.validate(query);
  if (error) {
    throw new UserError(`Invalid query format: ${error.message || error.toString()}`);
  }

  const validQuery = query.measures?.length ||
    query.dimensions?.length ||
    query.timeDimensions?.filter(td => !!td.granularity).length;
  if (!validQuery) {
    throw new UserError(
      'Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid'
    );
  }

  const regularToTimeDimension = (query.dimensions || []).filter(d => typeof d === 'string' && d.split('.').length === 3).map(d => ({
    dimension: d.split('.').slice(0, 2).join('.'),
    granularity: d.split('.')[2]
  }));
  const timezone = value.timezone || 'UTC';

  const def = getEnv('dbQueryDefaultLimit') <= getEnv('dbQueryLimit')
    ? getEnv('dbQueryDefaultLimit')
    : getEnv('dbQueryLimit');

  let newLimit;
  if (!persistent) {
    if (
      typeof query.limit === 'number' &&

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Add at least one measure, dimension, or a timeDimension with a granularity to the query.
  2. If the query was built dynamically, check the code path that produced an empty selection set.
  3. Use the /meta endpoint to verify the member names you are adding actually exist.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/cubejs-api-gateway/src/query.js:447 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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