cube-js/cube · error
Can't refresh pre-aggregation without measures and dimension
Error message
Can't refresh pre-aggregation without measures and dimensions: ${preAggregation.preAggregationName} What it means
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.
Source
Thrown at packages/cubejs-server-core/src/core/RefreshScheduler.ts:207
groupedPartitions: partitions.groupedPartitionPreAggregations,
};
}
protected async baseQueryForPreAggregation(
compilerApi: CompilerApi,
preAggregation,
queryingOptions: ScheduledRefreshQueryingOptions
) {
const compilers = await compilerApi.getCompilers();
const query = await compilerApi.createQueryByDataSource(compilers, queryingOptions);
if (preAggregation.preAggregation.partitionGranularity || preAggregation.preAggregation.type === 'rollup') {
return { ...queryingOptions, ...preAggregation.references, preAggregationId: preAggregation.id };
} else if (preAggregation.preAggregation.type === 'originalSql') {
const cubeFromPath = query.cubeEvaluator.cubeFromPath(preAggregation.cube);
const measuresCount = Object.keys(cubeFromPath.measures || {}).length;
const dimensionsCount = Object.keys(cubeFromPath.dimensions || {}).length;
if (measuresCount === 0 && dimensionsCount === 0) {
throw new Error(
`Can't refresh pre-aggregation without measures and dimensions: ${preAggregation.preAggregationName}`
);
}
return {
...queryingOptions,
...(
measuresCount &&
{ measures: [`${preAggregation.cube}.${Object.keys(cubeFromPath.measures)[0]}`] }
),
...(
dimensionsCount &&
{ dimensions: [`${preAggregation.cube}.${Object.keys(cubeFromPath.dimensions)[0]}`] }
)
};
} else {
throw new Error(
`Scheduled refresh is unsupported for ${preAggregation.preAggregation.type} of ${preAggregation.preAggregationName}`
);View on GitHub (pinned to 7d981676b3)
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
Example fix
// before
cube('Events', {
sql: 'SELECT * FROM events',
preAggregations: { main: { type: 'originalSql' } }
});
// after
cube('Events', {
sql: 'SELECT * FROM events',
measures: { count: { type: 'count' } },
preAggregations: { main: { type: 'originalSql' } }
}); Defensive patterns
Strategy: validation
Validate before calling
function validateOriginalSqlPreAgg(cube) {
const hasMeasures = Object.keys(cube.measures || {}).length > 0;
const hasDims = Object.keys(cube.dimensions || {}).length > 0;
if (!hasMeasures && !hasDims) throw new Error(`Cube ${cube.name} needs measures or dimensions for originalSql pre-aggregation`);
} Type guard
const refreshableOriginalSql = (pa: any): boolean =>
pa?.preAggregation?.type === 'originalSql' &&
(Object.keys(pa.cube?.measures ?? {}).length > 0 || Object.keys(pa.cube?.dimensions ?? {}).length > 0); Try / catch
try {
await refreshScheduler.refresh(preAggregation);
} catch (e) {
if (e.message.includes("Can't refresh pre-aggregation without measures and dimensions")) {
logger.warn(`Skipping ${e.message}`);
} else { throw e; }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- A user's selector doesn't match any of the pre-aggregations
- Pre-aggregation '${preAggregationName}' is already defined
- Scheduled refresh is unsupported for ${preAggregation.preAgg
- No job description provided
- Invalid Job query format: ${error.message || error.toString(
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/edbabb75b37253f5.
Report an issue: GitHub.