cube-js/cube · error · UserError

'${measureName}' references cubes that lead to row multiplic

Error message

'${measureName}' references cubes that lead to row multiplication. Please rewrite it using sub query.

What it means

Similar to the measure-sub-query check but per-measure: when building the join for a single measure's select, if the measure references cubes other than the key cube and the built join multiplies the key cube's rows, Cube throws this UserError advising a sub query rewrite.

Source

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

        this.collectMemberNamesFor.bind(this),
        'collectMemberNamesFor',
      );

      const nonViewMembers = memberNamesForMeasure
        .map(member => this.memberInstanceByPath(member))
        .filter(member => member.definition().ownedByCube);

      const cubes = this.collectFrom(nonViewMembers, this.collectCubeNamesFor.bind(this), 'collectCubeNamesFor');
      // Not using `collectJoinHintsFromMembers([measure])` because it would collect too many join hints from view
      const joinHints = [
        measure.joinHint,
        ...this.collectJoinHintsFromMembers(nonViewMembers),
      ];
      if (R.any(cubeName => keyCubeName !== cubeName, cubes)) {
        const measuresJoin = this.joinGraph.buildJoin(joinHints);
        if (measuresJoin.multiplicationFactor[keyCubeName]) {
          const measureName = measure.isMemberExpression ? measure.expressionName : measure.measure;
          throw new UserError(
            `'${measureName}' references cubes that lead to row multiplication. Please rewrite it using sub query.`
          );
        }
        return true;
      }
      return false;
    }).reduce((a, b) => a || b);
  }

  aggregateSubQueryMeasureJoin(keyCubeName, measures, measuresJoin, primaryKeyDimensions, measureSubQueryDimensions) {
    return this.ungroupedMeasureSelect(() => this.withCubeAliasPrefix(`${keyCubeName}_measure_join`,
      () => {
        const columns = primaryKeyDimensions.map(p => p.selectColumns()).concat(measures.map(m => m.selectColumns()))
          .filter(s => !!s).join(', ');
        return `SELECT ${columns} FROM ${this.joinQuery(measuresJoin, measureSubQueryDimensions)}`;
      }));
  }

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Move the referenced field into the key cube (denormalize) or use a rollup.
  2. Rewrite the measure as a sub query measure so its aggregation is isolated.
  3. Change the join direction so the referenced cube is on the one-side of the relationship.
  4. Add a view-level alias/join path that avoids the multiplied cube.

Example fix

// before (measure in Orders referencing Items across has-many)
measures: { totalItems: { type: 'count', sql: '${Items.id}' } }
// after (sub query measure)
measures: {
  totalItems: {
    type: 'number',
    sql: 'SELECT count(*) FROM ${Items.sql} WHERE ${Items.order_id} = ${Orders.id}',
    subQuery: true
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Try / catch

try {
  return await cubeApi.load(query);
} catch (e) {
  if (/references cubes that lead to row multiplication/.test(e.message)) {
    const measure = e.message.match(/'(.*?)' references/)?.[1];
    console.error(`Rewrite ${measure} using a sub query`);
  }
  throw e;
}

Prevention

When it happens

Trigger: buildJoinForMeasureSelect / buildMeasureGroupedCubePath: measure (or its view members) reference other cubes; R.any shows cubes differ from keyCubeName; joinGraph.buildJoin(joinHints).multiplicationFactor[keyCubeName] is truthy.

Common situations: A measure in a cube that pulls ${OtherCube.field} across a has-many join; view members whose join path fans out; schema refactors that turn a belongs-to join into has-many.

Related errors


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