{"record":{"id":"7631789e1cbdeb43","repo":"cube-js/cube","slug":"names-for-membertype-doesn-t-match-between-p","errorCode":null,"errorMessage":"Names for ${memberType} doesn't match between '${preAggA.cube}.${preAggA.preAggregationName}' and '${preAggB.cube}.${preAggB.preAggregationName}': ${JSON.stringify(preAggAMemberNames)} does not equal to ${JSON.stringify(preAggBMemberNames)}","messagePattern":"Names for (.+?) doesn't match between '(.+?)\\.(.+?)' and '(.+?)\\.(.+?)': (.+?) does not equal to (.+?)","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/PreAggregations.ts","lineNumber":1267,"sourceCode":"      return preAggObj;\n    }\n  }\n\n  public static checkPartitionGranularityDefined(cube: string, preAggregationName: string, preAggregation: PreAggregationForQuery): string {\n    if (!preAggregation.preAggregation.partitionGranularity) {\n      throw new UserError(`'${preAggregation.cube}.${preAggregation.preAggregationName}' referenced by '${cube}.${preAggregationName}' rollupLambda doesn't have partition granularity. Partition granularity is required if multiple rollups are provided.`);\n    }\n    return preAggregation.preAggregation.partitionGranularity;\n  }\n\n  public static memberNameMismatchValidation(preAggA: PreAggregationForQuery, preAggB: PreAggregationForQuery, memberType: 'measures' | 'dimensions' | 'timeDimensions') {\n    const preAggAMemberNames = PreAggregations.memberShortNames(preAggA.references[memberType]);\n    const preAggBMemberNames = PreAggregations.memberShortNames(preAggB.references[memberType]);\n    if (!R.equals(\n      preAggAMemberNames,\n      preAggBMemberNames\n    )) {\n      throw new UserError(`Names for ${memberType} doesn't match between '${preAggA.cube}.${preAggA.preAggregationName}' and '${preAggB.cube}.${preAggB.preAggregationName}': ${JSON.stringify(preAggAMemberNames)} does not equal to ${JSON.stringify(preAggBMemberNames)}`);\n    }\n  }\n\n  private static memberShortNames(memberArray: (string | PreAggregationTimeDimensionReference)[]): string[] {\n    return memberArray.map(member => {\n      if (typeof member !== 'string') {\n        return `${member.dimension.split('.')[1]}.${member.granularity}`;\n      } else {\n        return member.split('.').at(-1)!;\n      }\n    });\n  }\n\n  public rollupMatchResultDescriptions() {\n    return this.rollupMatchResults().map(p => ({\n      name: this.query.cubeEvaluator.pathFromArray([p.cube, p.preAggregationName]),\n      tableName: this.preAggregationTableName(p.cube, p.preAggregationName, p.preAggregation),\n      references: p.references,","sourceCodeStart":1249,"sourceCodeEnd":1285,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/PreAggregations.ts#L1249-L1285","documentation":"All rollups concatenated by a rollupLambda must expose identical member sets. memberNameMismatchValidation compares the short member names of measures (or dimensions/timeDimensions) between two referenced pre-aggregations with R.equals (order-sensitive); any mismatch throws this UserError listing both name arrays.","triggerScenarios":"During rollupLambda construction, consecutive referenced pre-aggregations have different sets/order of measures, dimensions, or timeDimensions in their references — e.g. one rollup includes an extra dimension or lists members in a different order.","commonSituations":"Adding a new dimension to one rollup in a lambda but not the others; members defined in different order across cubes; one rollup using a different time dimension path; a schema drift where one referenced pre-aggregation was updated alone.","solutions":["Make the measures/dimensions/timeDimensions lists identical (same members, same order) across all rollups referenced by the lambda.","Update the stale rollup that lacks the newly added member.","Check the JSON arrays in the error to identify which member is extra/missing/reordered and fix that definition."],"exampleFix":"// before\nordersA: { measures: [CUBE.count], dimensions: [Orders.status] }\nordersB: { measures: [CUBE.count], dimensions: [Orders.status, Orders.country] } // extra dimension\n// after\nordersA: { measures: [CUBE.count], dimensions: [Orders.status, Orders.country] }\nordersB: { measures: [CUBE.count], dimensions: [Orders.status, Orders.country] }","handlingStrategy":"validation","validationCode":"// Ensure identical member sets (names and order) across a lambda's rollups\nfunction unionCompatible(preAggs) {\n  const key = p => JSON.stringify([p.measures, p.dimensions, p.timeDimensions]);\n  const first = key(preAggs[0]);\n  if (!preAggs.every(p => key(p) === first)) throw new Error('Rollups in rollupLambda must have identical measures/dimensions/timeDimensions');\n}","typeGuard":"function sameMembers(a, b) { return JSON.stringify(a.references.measures) === JSON.stringify(b.references.measures) && JSON.stringify(a.references.dimensions) === JSON.stringify(b.references.dimensions) && JSON.stringify(a.references.timeDimensions) === JSON.stringify(b.references.timeDimensions); }","tryCatchPattern":"try { await cube.query(query); } catch (e) { if (/Names for .* doesn't match between/.test(e.message)) { console.error('Align member lists across lambda rollups per the diff in message:', e.message); } else throw e; }","preventionTips":["Generate lambda rollups from a shared factory so member lists stay in sync","When adding a member to one rollup, update every rollup in the same lambda","Keep member order identical across cubes","Add a schema test comparing references of all rollups per lambda"],"tags":["pre-aggregation","rollup-lambda","member-mismatch","union-compatibility"],"backgroundTag":"rollup-member-mismatch","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}