cube-js/cube · error · UserError

rollupLambda '${cube}.${preAggregationName}' should referenc

Error message

rollupLambda '${cube}.${preAggregationName}' should reference at least one rollup

What it means

A rollupLambda pre-aggregation must reference at least one other rollup via its rollups array. If resolving every referenced name (with canUsePreAggregation filtering) yields an empty list, Cube throws this UserError because a lambda with no source rollups has nothing to concatenate.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/PreAggregations.ts:1209

        leafMeasureMatch: joinResult.leafMeasureMatch,
        preAggregationsToJoin,
        rollupJoin,
      };
    } else if (preAggregation.type === 'rollupLambda') {
      // TODO evaluation optimizations. Should be cached or moved to compile time.
      const referencedPreAggregations = preAggObj.references.rollups.map(
        name => {
          const [referencedCube, referencedPreAggregation] = this.query.cubeEvaluator.parsePath('preAggregations', name);
          return this.evaluatedPreAggregationObj(
            referencedCube,
            referencedPreAggregation,
            this.query.cubeEvaluator.byPath('preAggregations', name) as PreAggregationDefinitionExtended,
            canUsePreAggregation
          );
        }
      );
      if (referencedPreAggregations.length === 0) {
        throw new UserError(`rollupLambda '${cube}.${preAggregationName}' should reference at least one rollup`);
      }
      referencedPreAggregations.forEach((referencedPreAggregation, i) => {
        if (i === referencedPreAggregations.length - 1 && preAggObj.preAggregation.unionWithSourceData && preAggObj.cube !== referencedPreAggregations[i].cube) {
          throw new UserError(`unionWithSourceData can be enabled only for pre-aggregation within '${preAggObj.cube}' cube but '${referencedPreAggregations[i].preAggregationName}' pre-aggregation is defined within '${referencedPreAggregations[i].cube}' cube`);
        }
        referencedPreAggregations[i] = {
          ...referencedPreAggregations[i],
          preAggregation: {
            ...referencedPreAggregations[i].preAggregation,
            unionWithSourceData: i === referencedPreAggregations.length - 1 ? preAggObj.preAggregation.unionWithSourceData : false,
            rollupLambdaId: `${cube}.${preAggregationName}`,
            lastRollupLambda: i === referencedPreAggregations.length - 1,
            rollupLambdaTimeDimensionsReference: preAggObj.references.timeDimensions,
          }
        };
        if (i > 0) {
          const partitionGranularity = PreAggregations.checkPartitionGranularityDefined(cube, preAggregationName, referencedPreAggregations[i]);
          const prevReferencedPreAggregation = referencedPreAggregations[i - 1];

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Add at least one valid rollup reference to the rollups array (full path 'CubeName.preAggregationName').
  2. Fix typos in the rollup names so they resolve to existing pre-aggregations.
  3. Check why referenced pre-aggregations are rejected by canUsePreAggregation (query shape mismatch) and align their definitions.

Example fix

// before
preAggregations: {
  monthlyUnion: { type: 'rollupLambda', rollups: [] }
}
// after
preAggregations: {
  monthlyUnion: { type: 'rollupLambda', rollups: [CUBE.ordersByMonth] },
  ordersByMonth: { measures: [CUBE.count], timeDimension: Orders.createdAt, granularity: 'month' }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate rollupLambda rollups resolve to existing pre-aggregations
function validateRollupLambda(def, schema) {
  if (def.type === 'rollupLambda') {
    const resolvable = (def.rollups || []).filter(r => schema.cubeExists(r.split('.')[0]) && schema.preAggregationExists(r));
    if (resolvable.length === 0) throw new Error('rollupLambda must reference at least one existing rollup');
  }
}

Type guard

function hasRollupReferences(def) { return def?.type === 'rollupLambda' && Array.isArray(def.rollups) && def.rollups.length > 0; }

Try / catch

try { await cube.query(query); } catch (e) { if (/should reference at least one rollup/.test(e.message)) { console.error('Add valid entries to the rollups array:', e.message); } else throw e; }

Prevention

When it happens

Trigger: Defining preAggregations: { myLambda: { type: 'rollupLambda', rollups: [...] } } where the rollups list is empty, references only non-pre-aggregation paths, or all referenced pre-aggregations are filtered out by canUsePreAggregation during buildRollupLambdaPreAggregations.

Common situations: Typos in rollup names so the paths don't resolve; rollups array left empty; referencing pre-aggregations that were renamed or removed in a refactor; referencing rollups defined with a query shape that can never be used so all candidates are filtered out.

Related errors


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