cube-js/cube · error · UserError

No rollups found that can be used for a rollup join from "${

Error message

No rollups found that can be used for a rollup join from "${join.from}" (fromMembers: ${JSON.stringify(join.fromMembers)}) to "${join.to}" (toMembers: ${JSON.stringify(join.toMembers)}). Check the "${rollupJoinPreAggName}" pre-aggregation definition — you may have forgotten to specify the full dimension paths

What it means

For each join in a rollupJoin, Cube must find exactly one rollup pre-aggregation that contains all the dimension members of that join's side (fromMembers/toMembers). If no candidate pre-aggregation references every required member, this UserError fires and points at the rollupJoin definition — typically because abbreviated dimension paths were used instead of full Cube.dimension paths.

Source

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

        });
      }
    );
  }

  private preAggObjForJoin(
    preAggObjsToJoin: PreAggregationForQuery[],
    joinMembers: string[],
    join: JoinEdgeWithMembers,
    rollupJoinPreAggName: string,
  ): PreAggregationForQuery {
    const fromPreAggObj = preAggObjsToJoin
      .filter(p => joinMembers.every(m => !!p.references.dimensions.find(d => m === d)));
    if (!fromPreAggObj.length) {
      const msg = `No rollups found that can be used for a rollup join from "${
        join.from}" (fromMembers: ${JSON.stringify(join.fromMembers)}) to "${join.to}" (toMembers: ${
        JSON.stringify(join.toMembers)}). Check the "${
        rollupJoinPreAggName}" pre-aggregation definition — you may have forgotten to specify the full dimension paths`;
      throw new UserError(msg);
    }
    if (fromPreAggObj.length > 1) {
      throw new UserError(
        `Multiple rollups found that can be used for rollup join ${JSON.stringify(join)}: ${fromPreAggObj.map(p => this.preAggregationId(p)).join(', ')}`,
      );
    }
    return fromPreAggObj[0];
  }

  private resolveJoinMembers(join: FinishedJoinTree): JoinEdgeWithMembers[] {
    const joinMap = new Set<string>();

    return join.joins.map(j => {
      joinMap.add(j.originalFrom);

      const memberPaths = this.query.collectMemberNamesFor(() => this.query.evaluateSql(j.originalFrom, j.join.sql)).map(m => m.split('.'));

      const invalidMembers = memberPaths.filter(m => !joinMap.has(m[0]) && m[0] !== j.originalTo);

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Use fully qualified member paths everywhere (e.g. Users.country, not 'country') in rollupJoin from/to and pre-aggregation dimensions.
  2. Ensure each side's pre-aggregation includes the join key dimensions in its references.dimensions.
  3. Check for renamed dimensions/members and update the rollupJoin definition accordingly.
  4. Verify exactly one matching rollup exists per join side — zero triggers this error, more than one throws the 'Multiple rollups found' companion error.

Example fix

// before
rollupJoin: [{ from: 'Users', to: 'Orders', fromMembers: ['country'], toMembers: ['userCountry'] }]
// after
rollupJoin: [{ from: 'Users', to: 'Orders', fromMembers: ['Users.country'], toMembers: ['Orders.userCountry'] }]
Defensive patterns

Strategy: validation

Validate before calling

// verify each rollupJoin member appears in the referenced pre-aggregation's dimensions
const isFullPath = (m) => /^[A-Za-z_]\w*\.[A-Za-z_]\w*$/.test(m);
for (const j of rollupJoin) {
  [...j.fromMembers, ...j.toMembers].forEach(m => {
    if (!isFullPath(m)) throw new Error(`rollupJoin member '${m}' must be a full path like Users.country`);
  });
}

Type guard

const isFullyQualifiedMember = (m: string): m is `${string}.${string}` => /^[A-Za-z_]\w*\.[A-Za-z_]\w*$/.test(m);

Try / catch

try { await cubeApi.load(query); } catch (e) { if (/No rollups found that can be used for a rollup join/.test(e.message)) {
  const preAggName = e.message.match(/Check the "([^"]+)"/)?.[1];
  throw new Error(`Add full dimension paths to pre-aggregation '${preAggName}'`); } throw e; }

Prevention

When it happens

Trigger: A rollupJoin references pre-aggregations whose references.dimensions do not include all members of join.fromMembers or join.toMembers — e.g. members written as 'country' or 'Users.country' instead of the fully qualified path in the join definition or the pre-agg dimensions.

Common situations: Copy-pasted rollupJoin examples with partial member paths; pre-aggregation defined on a subset of dimensions not covering the join keys; renaming dimensions without updating rollupJoin member references.

Related errors


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