{"record":{"id":"8f404080fbaf360c","repo":"cube-js/cube","slug":"can-t-find-join-path-to-join-cubestojoin-map-v","errorCode":null,"errorMessage":"Can't find join path to join ${cubesToJoin.map(v => `'${v}'`).join(', ')}","messagePattern":"Can't find join path to join (.+?)'`\\)\\.join\\(', '\\)\\}","errorType":"exception","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/compiler/JoinGraph.ts","lineNumber":195,"sourceCode":"    const key = JSON.stringify(cubesToJoin);\n    if (!this.builtJoins[key]) {\n      const join = R.pipe<\n          JoinHints,\n          Array<JoinTree | null>,\n          Array<JoinTree>,\n          Array<JoinTree>\n      >(\n        R.map(\n          (cube: JoinHint): JoinTree | null => this.buildJoinTreeForRoot(cube, R.without([cube], cubesToJoin))\n        ),\n        // @ts-ignore\n        R.filter(R.identity),\n        R.sortBy((joinTree: JoinTree) => joinTree.joins.length)\n      // @ts-ignore\n      )(cubesToJoin)[0];\n\n      if (!join) {\n        throw new UserError(`Can't find join path to join ${cubesToJoin.map(v => `'${v}'`).join(', ')}`);\n      }\n\n      this.builtJoins[key] = Object.assign(join, {\n        multiplicationFactor: R.compose<\n          JoinHints,\n          Array<[string, boolean]>,\n          Record<string, boolean>\n        >(\n          R.fromPairs,\n          R.map(v => [this.cubeFromPath(v), this.findMultiplicationFactorFor(this.cubeFromPath(v), join.joins)])\n        )(cubesToJoin)\n      });\n    }\n    return this.builtJoins[key];\n  }\n\n  protected cubeFromPath(cubePath) {\n    if (Array.isArray(cubePath)) {","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/compiler/JoinGraph.ts#L177-L213","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: orders and shipping have no path\n// after (in orders schema)\njoins: {\n  shipping: { sql: \"${CUBE}.shipment_id = ${shipping}.id\", relationship: 'belongsTo' }\n}","handlingStrategy":"validation","validationCode":"function allCubesConnected(compiler) {\n  // build join graph before issuing queries\n  compiler.buildJoinGraph();\n  // each queried cube pair must be in the same connected component\n  return compiler.getJoinGraph().nodes();\n}","typeGuard":null,"tryCatchPattern":"try {\n  const result = await cube.query(query);\n} catch (e) {\n  if (String(e.message).startsWith(\"Can't find join path\")) {\n    console.error('Add joins between the referenced cubes or split the query:', e.message);\n  }\n}","preventionTips":["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"],"tags":["joins","query-planning","schema-compiler"],"backgroundTag":"no-join-path","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}