{"record":{"id":"30ca97845c0a5524","repo":"cube-js/cube","slug":"unionwithsourcedata-can-be-enabled-only-for-pre-ag","errorCode":null,"errorMessage":"unionWithSourceData can be enabled only for pre-aggregation within '${preAggObj.cube}' cube but '${referencedPreAggregations[i].preAggregationName}' pre-aggregation is defined within '${referencedPreAggregations[i].cube}' cube","messagePattern":"unionWithSourceData can be enabled only for pre-aggregation within '(.+?)' cube but '(.+?)' pre-aggregation is defined within '(.+?)' cube","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/PreAggregations.ts","lineNumber":1213,"sourceCode":"    } else if (preAggregation.type === 'rollupLambda') {\n      // TODO evaluation optimizations. Should be cached or moved to compile time.\n      const referencedPreAggregations = preAggObj.references.rollups.map(\n        name => {\n          const [referencedCube, referencedPreAggregation] = this.query.cubeEvaluator.parsePath('preAggregations', name);\n          return this.evaluatedPreAggregationObj(\n            referencedCube,\n            referencedPreAggregation,\n            this.query.cubeEvaluator.byPath('preAggregations', name) as PreAggregationDefinitionExtended,\n            canUsePreAggregation\n          );\n        }\n      );\n      if (referencedPreAggregations.length === 0) {\n        throw new UserError(`rollupLambda '${cube}.${preAggregationName}' should reference at least one rollup`);\n      }\n      referencedPreAggregations.forEach((referencedPreAggregation, i) => {\n        if (i === referencedPreAggregations.length - 1 && preAggObj.preAggregation.unionWithSourceData && preAggObj.cube !== referencedPreAggregations[i].cube) {\n          throw new UserError(`unionWithSourceData can be enabled only for pre-aggregation within '${preAggObj.cube}' cube but '${referencedPreAggregations[i].preAggregationName}' pre-aggregation is defined within '${referencedPreAggregations[i].cube}' cube`);\n        }\n        referencedPreAggregations[i] = {\n          ...referencedPreAggregations[i],\n          preAggregation: {\n            ...referencedPreAggregations[i].preAggregation,\n            unionWithSourceData: i === referencedPreAggregations.length - 1 ? preAggObj.preAggregation.unionWithSourceData : false,\n            rollupLambdaId: `${cube}.${preAggregationName}`,\n            lastRollupLambda: i === referencedPreAggregations.length - 1,\n            rollupLambdaTimeDimensionsReference: preAggObj.references.timeDimensions,\n          }\n        };\n        if (i > 0) {\n          const partitionGranularity = PreAggregations.checkPartitionGranularityDefined(cube, preAggregationName, referencedPreAggregations[i]);\n          const prevReferencedPreAggregation = referencedPreAggregations[i - 1];\n          const partitionGranularityPrev = PreAggregations.checkPartitionGranularityDefined(cube, preAggregationName, prevReferencedPreAggregation);\n          const minGranularity = this.query.minGranularity(partitionGranularityPrev, partitionGranularity);\n          if (minGranularity !== partitionGranularity) {\n            throw new UserError(`'${prevReferencedPreAggregation.cube}.${prevReferencedPreAggregation.preAggregationName}' and '${referencedPreAggregation.cube}.${referencedPreAggregation.preAggregationName}' referenced by '${cube}.${preAggregationName}' rollupLambda have incompatible partition granularities. '${partitionGranularityPrev}' can't be padded by '${partitionGranularity}'`);","sourceCodeStart":1195,"sourceCodeEnd":1231,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/PreAggregations.ts#L1195-L1231","documentation":"When the last rollup referenced by a rollupLambda has unionWithSourceData enabled, Cube requires it to live in the same cube as the lambda itself, because unioning source data is only valid within the lambda's own cube. Cross-cube usage throws this UserError.","triggerScenarios":"A rollupLambda on cube A sets unionWithSourceData: true, and the final entry in its rollups array resolves to a pre-aggregation defined on cube B (preAggObj.cube !== referencedPreAggregations[last].cube).","commonSituations":"Configuring unionWithSourceData on a lambda whose last rollup comes from another cube's pre-aggregation; moving a rollup to another cube during refactoring while keeping unionWithSourceData; misunderstanding that the flag applies to the lambda's cube, not any referenced rollup.","solutions":["Make the last rollup in the rollups array a pre-aggregation defined in the same cube as the rollupLambda.","Set unionWithSourceData: false (or remove it) if cross-cube unioning is not actually needed.","Move the rollupLambda definition into the cube that owns the referenced pre-aggregation."],"exampleFix":"// before\n// Cube A\nmonthlyUnion: { type: 'rollupLambda', unionWithSourceData: true, rollups: [B.ordersByMonth] }\n// after\n// Cube A\nmonthlyUnion: { type: 'rollupLambda', unionWithSourceData: true, rollups: [A.ordersByMonth] } // same cube\nB_orders: { type: 'rollupLambda', rollups: [B.ordersByMonth] } // or lambda in B","handlingStrategy":"validation","validationCode":"// unionWithSourceData requires the last rollup to live in the same cube as the lambda\nfunction validateUnionWithSourceData(lambdaCube, def, rollupCubes) {\n  if (def.unionWithSourceData && rollupCubes[rollupCubes.length - 1] !== lambdaCube) {\n    throw new Error(`Last rollup (${rollupCubes[rollupCubes.length - 1]}) must be in cube ${lambdaCube} when unionWithSourceData is true`);\n  }\n}","typeGuard":"null","tryCatchPattern":"try { await cube.query(query); } catch (e) { if (/unionWithSourceData can be enabled only for pre-aggregation within/.test(e.message)) { console.error('Move the last rollup into the lambda cube or disable unionWithSourceData:', e.message); } else throw e; }","preventionTips":["Only enable unionWithSourceData when the final rollup is defined in the lambda's cube","Re-check the flag after moving pre-aggregations between cubes","Document cube ownership for each pre-aggregation in multi-cube schemas","Cover rollupLambdas with compile tests"],"tags":["pre-aggregation","rollup-lambda","union-with-source-data","cross-cube"],"backgroundTag":"rollup-lambda-cross-cube-union","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}