cube-js/cube · error · UserError

'${preAggregation.cube}.${preAggregation.preAggregationName}

Error message

'${preAggregation.cube}.${preAggregation.preAggregationName}' referenced by '${cube}.${preAggregationName}' rollupLambda doesn't have partition granularity. Partition granularity is required if multiple rollups are provided.

What it means

When a rollupLambda references multiple rollups, every referenced pre-aggregation must define partitionGranularity, since concatenation of partitions requires each source rollup to be partitioned. This static check throws if any referenced pre-aggregation lacks it.

Source

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

      });
      referencedPreAggregations.forEach(preAgg => {
        references.rollupsReferences.push(preAgg.references);
      });
      const lambdaResult = canUsePreAggregation(references);
      return {
        ...preAggObj,
        canUsePreAggregation: lambdaResult.canUse,
        leafMeasureMatch: lambdaResult.leafMeasureMatch,
        referencedPreAggregations,
      };
    } else {
      return preAggObj;
    }
  }

  public static checkPartitionGranularityDefined(cube: string, preAggregationName: string, preAggregation: PreAggregationForQuery): string {
    if (!preAggregation.preAggregation.partitionGranularity) {
      throw new UserError(`'${preAggregation.cube}.${preAggregation.preAggregationName}' referenced by '${cube}.${preAggregationName}' rollupLambda doesn't have partition granularity. Partition granularity is required if multiple rollups are provided.`);
    }
    return preAggregation.preAggregation.partitionGranularity;
  }

  public static memberNameMismatchValidation(preAggA: PreAggregationForQuery, preAggB: PreAggregationForQuery, memberType: 'measures' | 'dimensions' | 'timeDimensions') {
    const preAggAMemberNames = PreAggregations.memberShortNames(preAggA.references[memberType]);
    const preAggBMemberNames = PreAggregations.memberShortNames(preAggB.references[memberType]);
    if (!R.equals(
      preAggAMemberNames,
      preAggBMemberNames
    )) {
      throw new UserError(`Names for ${memberType} doesn't match between '${preAggA.cube}.${preAggA.preAggregationName}' and '${preAggB.cube}.${preAggB.preAggregationName}': ${JSON.stringify(preAggAMemberNames)} does not equal to ${JSON.stringify(preAggBMemberNames)}`);
    }
  }

  private static memberShortNames(memberArray: (string | PreAggregationTimeDimensionReference)[]): string[] {
    return memberArray.map(member => {
      if (typeof member !== 'string') {

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Add partitionGranularity: 'month' (or day/week/year) to every pre-aggregation referenced by a multi-rollup rollupLambda.
  2. If a rollup should not be partitioned, remove it from the multi-rollup lambda or give it its own lambda.
  3. Audit all rollups listed in rollups arrays for the partitionGranularity key.

Example fix

// before
ordersByMonth: { measures: [CUBE.count], timeDimension: Orders.createdAt, granularity: 'month' }
// after
ordersByMonth: { measures: [CUBE.count], timeDimension: Orders.createdAt, granularity: 'month', partitionGranularity: 'month' }
Defensive patterns

Strategy: validation

Validate before calling

// Require partitionGranularity on every rollup referenced by a multi-rollup rollupLambda
function requirePartitionGranularity(def, preAggDefs) {
  if (def.type === 'rollupLambda' && (def.rollups || []).length > 1) {
    for (const r of def.rollups) {
      if (!preAggDefs[r]?.partitionGranularity) throw new Error(`${r} needs partitionGranularity for multi-rollup rollupLambda`);
    }
  }
}

Type guard

function isPartitioned(p) { return typeof p?.partitionGranularity === 'string' && p.partitionGranularity.length > 0; }

Try / catch

try { await cube.query(query); } catch (e) { if (/doesn't have partition granularity/.test(e.message)) { console.error('Add partitionGranularity to the referenced rollup:', e.message); } else throw e; }

Prevention

When it happens

Trigger: checkPartitionGranularityDefined is called during rollupLambda building with 2+ referenced rollups, and one of them (or one defined via a reference without partitionGranularity) has no partitionGranularity set in its definition.

Common situations: Adding a second rollup to an existing lambda while the first/second rollup was never partitioned; pre-aggregations defined before partitionGranularity existed (older schemas); referencing a shared pre-aggregation that other queries use unpartitioned.

Related errors


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