{"record":{"id":"4b5fb4bb3c4a93ac","repo":"cube-js/cube","slug":"query-should-contain-either-measures-dimensions-o","errorCode":null,"errorMessage":"Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid","messagePattern":"Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-api-gateway/src/query.js","lineNumber":447,"sourceCode":" * @param {Query} query\n * @param {boolean} persistent\n * @param {CacheMode} [cacheMode]\n * @throws {UserError}\n * @returns {import('./types/query').NormalizedQuery}\n */\nconst normalizeQuery = (query, persistent, cacheMode) => {\n  query = normalizeQueryCacheMode(query, cacheMode);\n  query.timezone = query.timezone || getEnv('defaultTimezone');\n  const { error, value } = querySchema.validate(query);\n  if (error) {\n    throw new UserError(`Invalid query format: ${error.message || error.toString()}`);\n  }\n\n  const validQuery = query.measures?.length ||\n    query.dimensions?.length ||\n    query.timeDimensions?.filter(td => !!td.granularity).length;\n  if (!validQuery) {\n    throw new UserError(\n      'Query should contain either measures, dimensions or timeDimensions with granularities in order to be valid'\n    );\n  }\n\n  const regularToTimeDimension = (query.dimensions || []).filter(d => typeof d === 'string' && d.split('.').length === 3).map(d => ({\n    dimension: d.split('.').slice(0, 2).join('.'),\n    granularity: d.split('.')[2]\n  }));\n  const timezone = value.timezone || 'UTC';\n\n  const def = getEnv('dbQueryDefaultLimit') <= getEnv('dbQueryLimit')\n    ? getEnv('dbQueryDefaultLimit')\n    : getEnv('dbQueryLimit');\n\n  let newLimit;\n  if (!persistent) {\n    if (\n      typeof query.limit === 'number' &&","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-api-gateway/src/query.js#L429-L465","documentation":"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.","triggerScenarios":"Thrown at packages/cubejs-api-gateway/src/query.js:447 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Add at least one measure, dimension, or a timeDimension with a granularity to the query.","If the query was built dynamically, check the code path that produced an empty selection set.","Use the /meta endpoint to verify the member names you are adding actually exist."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}