cube-js/cube · error · UserError

'${measures.map(m => m.measure).join(', ')}' reference cubes

Error message

'${measures.map(m => m.measure).join(', ')}' reference cubes that lead to row multiplication.

What it means

When Cube builds a join for selected measures in a sub query/aggregation context, it checks whether the join causes row multiplication for the key cube. If measures reference cubes whose join multiplies rows of the key cube, the aggregated result would be wrong, so Cube throws this UserError listing the offending measures.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:2521

  aggregateSubQuery(keyCubeName, measures, filters) {
    filters = filters || this.allFilters;
    const primaryKeyDimensions = this.primaryKeyNames(keyCubeName).map((k) => this.newDimension(k));
    const shouldBuildJoinForMeasureSelect = this.checkShouldBuildJoinForMeasureSelect(measures, keyCubeName);

    let keyCubeSql;
    let keyCubeAlias;
    let keyCubeInlineLeftJoinConditions;
    const measureSubQueryDimensions = this.collectFrom(
      measures,
      this.collectSubQueryDimensionsFor.bind(this),
      'collectSubQueryDimensionsFor'
    );

    if (shouldBuildJoinForMeasureSelect) {
      const joinHints = this.collectJoinHintsFromMembers(measures);
      const measuresJoin = this.joinGraph.buildJoin(joinHints);
      if (measuresJoin.multiplicationFactor[keyCubeName]) {
        throw new UserError(
          `'${measures.map(m => m.measure).join(', ')}' reference cubes that lead to row multiplication.`
        );
      }
      keyCubeSql = `(${this.aggregateSubQueryMeasureJoin(keyCubeName, measures, measuresJoin, primaryKeyDimensions, measureSubQueryDimensions)})`;
      keyCubeAlias = this.cubeAlias(keyCubeName);
    } else {
      [keyCubeSql, keyCubeAlias, keyCubeInlineLeftJoinConditions] = this.rewriteInlineCubeSql(keyCubeName);
    }

    const measureSelectFn = () => measures.map(m => m.selectColumns());
    const selectedMeasures = shouldBuildJoinForMeasureSelect ? this.evaluateSymbolSqlWithContext(
      measureSelectFn,
      {
        ungroupedAliases: R.fromPairs(measures.map(m => [m.measure, m.aliasName()]))
      }
    ) : measureSelectFn();
    const columnsForSelect = this
      .dimensionColumns(this.escapeColumnName(QueryAlias.AGG_SUB_QUERY_KEYS))

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Rewrite one of the measures as a sub query measure so it aggregates independently before joining.
  2. Denormalize the needed value into the key cube (e.g. via a rollup or precomputed column).
  3. Restructure the joins so the measures' cube is on the one-side (belongs-to) relative to the key cube.
  4. Split the query into multiple queries and combine client-side.

Example fix

// before (measure from multiplied joined cube in same query)
measures: { ordersCount: C.count, revenue: Orders.revenue, refunds: Refunds.amount }
// after (rewrite Refunds.amount as sub query measure)
measures: {
  ordersCount: Orders.count,
  revenue: Orders.revenue,
  refunds: { sql: 'SELECT sum(amount) FROM ${Refunds.sql} WHERE ${Refunds.order_id} = ${Orders.id}', type: 'number', subQuery: true }
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Try / catch

try {
  return await cubeApi.load(query);
} catch (e) {
  if (/reference cubes that lead to row multiplication/.test(e.message)) {
    console.error('Rewrite one of the listed measures as a subQuery measure:', e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: aggregateSubQueryMeasureJoin path: measures collected for a measure-sub-query span multiple cubes, joinGraph.buildJoin(joinHints) yields measuresJoin.multiplicationFactor[keyCubeName] > 1, i.e. a has-many join path between the key cube and the measures' cubes.

Common situations: Sub queries over joined fact tables where measures come from different many-side tables; views mixing measures from fan-out joined cubes; adding a second measure from another fact table to an existing dashboard query.

Related errors


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