{"record":{"id":"edbabb75b37253f5","repo":"cube-js/cube","slug":"can-t-refresh-pre-aggregation-without-measures-and","errorCode":null,"errorMessage":"Can't refresh pre-aggregation without measures and dimensions: ${preAggregation.preAggregationName}","messagePattern":"Can't refresh pre-aggregation without measures and dimensions: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cubejs-server-core/src/core/RefreshScheduler.ts","lineNumber":207,"sourceCode":"      groupedPartitions: partitions.groupedPartitionPreAggregations,\n    };\n  }\n\n  protected async baseQueryForPreAggregation(\n    compilerApi: CompilerApi,\n    preAggregation,\n    queryingOptions: ScheduledRefreshQueryingOptions\n  ) {\n    const compilers = await compilerApi.getCompilers();\n    const query = await compilerApi.createQueryByDataSource(compilers, queryingOptions);\n    if (preAggregation.preAggregation.partitionGranularity || preAggregation.preAggregation.type === 'rollup') {\n      return { ...queryingOptions, ...preAggregation.references, preAggregationId: preAggregation.id };\n    } else if (preAggregation.preAggregation.type === 'originalSql') {\n      const cubeFromPath = query.cubeEvaluator.cubeFromPath(preAggregation.cube);\n      const measuresCount = Object.keys(cubeFromPath.measures || {}).length;\n      const dimensionsCount = Object.keys(cubeFromPath.dimensions || {}).length;\n      if (measuresCount === 0 && dimensionsCount === 0) {\n        throw new Error(\n          `Can't refresh pre-aggregation without measures and dimensions: ${preAggregation.preAggregationName}`\n        );\n      }\n      return {\n        ...queryingOptions,\n        ...(\n          measuresCount &&\n            { measures: [`${preAggregation.cube}.${Object.keys(cubeFromPath.measures)[0]}`] }\n        ),\n        ...(\n          dimensionsCount &&\n            { dimensions: [`${preAggregation.cube}.${Object.keys(cubeFromPath.dimensions)[0]}`] }\n        )\n      };\n    } else {\n      throw new Error(\n        `Scheduled refresh is unsupported for ${preAggregation.preAggregation.type} of ${preAggregation.preAggregationName}`\n      );","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-server-core/src/core/RefreshScheduler.ts#L189-L225","documentation":"When building the base query used to refresh an originalSql pre-aggregation, RefreshScheduler needs at least one measure or one dimension on the source cube to form a meaningful refresh query. If the cube behind the pre-aggregation defines neither, Cube throws this error because there is nothing to select.","triggerScenarios":"Scheduled refresh (or refreshScheduler via baseQuery -> baseQueryForPreAggregation) processes a preAggregation of type 'originalSql' whose cubeFromPath has zero measures AND zero dimensions in its data model.","commonSituations":"A data model file defines a cube with only pre-aggregations (or only segments/joins) and an originalSql pre-aggregation but no measures/dimensions; typos so measures land outside the cube; auto-generated models stripped of measures.","solutions":["Add at least one measure or dimension to the cube referenced by the originalSql pre-aggregation","Remove the originalSql pre-aggregation if the cube intentionally has no measures/dimensions","Change the pre-aggregation type to one with explicit rollup references (rollup with measures/dimensions) that doesn't rely on the cube's own measures/dimensions","Check the referenced cube path (preAggregation.cube) — the counts come from cubeEvaluator.cubeFromPath, so the measures may exist in another cube than you assume"],"exampleFix":"// before\ncube('Events', {\n  sql: 'SELECT * FROM events',\n  preAggregations: { main: { type: 'originalSql' } }\n});\n// after\ncube('Events', {\n  sql: 'SELECT * FROM events',\n  measures: { count: { type: 'count' } },\n  preAggregations: { main: { type: 'originalSql' } }\n});","handlingStrategy":"validation","validationCode":"function validateOriginalSqlPreAgg(cube) {\n  const hasMeasures = Object.keys(cube.measures || {}).length > 0;\n  const hasDims = Object.keys(cube.dimensions || {}).length > 0;\n  if (!hasMeasures && !hasDims) throw new Error(`Cube ${cube.name} needs measures or dimensions for originalSql pre-aggregation`);\n}","typeGuard":"const refreshableOriginalSql = (pa: any): boolean =>\n  pa?.preAggregation?.type === 'originalSql' &&\n  (Object.keys(pa.cube?.measures ?? {}).length > 0 || Object.keys(pa.cube?.dimensions ?? {}).length > 0);","tryCatchPattern":"try {\n  await refreshScheduler.refresh(preAggregation);\n} catch (e) {\n  if (e.message.includes(\"Can't refresh pre-aggregation without measures and dimensions\")) {\n    logger.warn(`Skipping ${e.message}`);\n  } else { throw e; }\n}","preventionTips":["Ensure every cube with an originalSql pre-aggregation defines at least one measure or dimension","Lint data models for cubes containing only pre-aggregations","Check the referenced cube path when using joins/namespaced cubes"],"tags":["data-model","pre-aggregations","schema-compiler"],"backgroundTag":"invalid-preaggregation-definition","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}