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
- Define joins between the cubes (directly or via an intermediate cube) so a path exists in the join graph
- Split the query so each part only touches connected cubes
- Verify join definitions reference current cube names (check for renames)
- 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
- Define joins whenever you add a cube that will be queried together with others
- Keep cube names referenced in joins in sync after renames
- Model shared dimensions and join them to every fact cube
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
- Expected one parameter but nothing found
- Expected only 2 parameters for timestamp filter but got: ${t
- Unsupported timestamp precision: ${this.query.timestampPreci
- Unsupported measure type replacement for ${sourceMeasure}: $
- Unsupported additional filters for measure ${sourceMeasure}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/8f404080fbaf360c.
Report an issue: GitHub.