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
- Move the referenced field into the key cube (denormalize) or use a rollup.
- Rewrite the measure as a sub query measure so its aggregation is isolated.
- Change the join direction so the referenced cube is on the one-side of the relationship.
- 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
- Keep each measure's references within its own cube or one-side joins
- Rewrite cross-cube measures as subQuery measures at schema design time
- Review join direction changes in code review for fan-out risk
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
- Dimension-only measure ${measureName} references cubes (${cu
- '${measures.map(m => m.measure).join(', ')}' reference cubes
- Measure filters aren't allowed in ungrouped query
- Subquery measure ${m.expressionName} should reference at lea
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/8e358a2d7e7d1715.
Report an issue: GitHub.