cube-js/cube · error · UserError

Can't find join path to join ${cubesToJoin.map(v => `'${v}'`

Error message

Can't find join path to join ${cubesToJoin.map(v => `'${v}'`).join(', ')}

What it means

JoinGraph.buildJoin computes the shortest join tree connecting the requested cubes; when no sequence of joins connects them, it throws UserError 'Can't find join path to join 'a', 'b''. Cube requires a connected graph of explicit join definitions between all cubes referenced by a query.

Source

Thrown at packages/cubejs-schema-compiler/src/compiler/JoinGraph.ts:195

    const key = JSON.stringify(cubesToJoin);
    if (!this.builtJoins[key]) {
      const join = R.pipe<
          JoinHints,
          Array<JoinTree | null>,
          Array<JoinTree>,
          Array<JoinTree>
      >(
        R.map(
          (cube: JoinHint): JoinTree | null => this.buildJoinTreeForRoot(cube, R.without([cube], cubesToJoin))
        ),
        // @ts-ignore
        R.filter(R.identity),
        R.sortBy((joinTree: JoinTree) => joinTree.joins.length)
      // @ts-ignore
      )(cubesToJoin)[0];

      if (!join) {
        throw new UserError(`Can't find join path to join ${cubesToJoin.map(v => `'${v}'`).join(', ')}`);
      }

      this.builtJoins[key] = Object.assign(join, {
        multiplicationFactor: R.compose<
          JoinHints,
          Array<[string, boolean]>,
          Record<string, boolean>
        >(
          R.fromPairs,
          R.map(v => [this.cubeFromPath(v), this.findMultiplicationFactorFor(this.cubeFromPath(v), join.joins)])
        )(cubesToJoin)
      });
    }
    return this.builtJoins[key];
  }

  protected cubeFromPath(cubePath) {
    if (Array.isArray(cubePath)) {

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Define joins between the cubes (directly or via an intermediate cube) so a path exists in the join graph
  2. Split the query so each part only touches connected cubes
  3. Verify join definitions reference current cube names (check for renames)
  4. Add a shared dimension cube with joins to both if a bridging relationship exists

Example fix

// before: orders and shipping have no path
// after (in orders schema)
joins: {
  shipping: { sql: "${CUBE}.shipment_id = ${shipping}.id", relationship: 'belongsTo' }
}
Defensive patterns

Strategy: validation

Validate before calling

function allCubesConnected(compiler) {
  // build join graph before issuing queries
  compiler.buildJoinGraph();
  // each queried cube pair must be in the same connected component
  return compiler.getJoinGraph().nodes();
}

Try / catch

try {
  const result = await cube.query(query);
} catch (e) {
  if (String(e.message).startsWith("Can't find join path")) {
    console.error('Add joins between the referenced cubes or split the query:', e.message);
  }
}

Prevention

When it happens

Trigger: Executing a query whose query.tables / measures reference cubes that have no transitive join path — e.g. querying measures from two cubes whose only relationship is indirect through a cube without joins defined.

Common situations: Adding a new cube without defining joins, querying measures across fact tables that were never joined, renaming a cube so existing joins reference a stale name, or in multi-fact-table analytics setups.

Related errors


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