{"record":{"id":"76ef407f8c01edbf","repo":"cube-js/cube","slug":"one-or-more-primary-key-is-required-for-cubenam","errorCode":null,"errorMessage":"One or more Primary key is required for '${cubeName}' cube","messagePattern":"One or more Primary key is required for '(.+?)' cube","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-schema-compiler/src/adapter/BaseQuery.js","lineNumber":3709,"sourceCode":"  }\n\n  autoPrefixAndEvaluateSql(cubeName, sql, isMemberExpr = false) {\n    return this.autoPrefixWithCubeName(cubeName, this.evaluateSql(cubeName, sql), isMemberExpr);\n  }\n\n  concatStringsSql(strings) {\n    return strings.join(' || ');\n  }\n\n  /**\n   *\n   * @param {string} cubeName\n   * @returns {Array<string>}\n   */\n  primaryKeyNames(cubeName) {\n    const primaryKeys = this.cubeEvaluator.primaryKeys[cubeName];\n    if (!primaryKeys || !primaryKeys.length) {\n      throw new UserError(`One or more Primary key is required for '${cubeName}' cube`);\n    }\n    return primaryKeys.map((pk) => this.primaryKeyName(cubeName, pk));\n  }\n\n  primaryKeyName(cubeName, primaryKey) {\n    return `${cubeName}.${primaryKey}`;\n  }\n\n  evaluateSql(cubeName, sql, options) {\n    options = options || {};\n    const self = this;\n    const { cubeEvaluator } = this;\n    return cubeEvaluator.resolveSymbolsCall(sql, (name) => {\n      const nextCubeName = cubeEvaluator.symbols[name] && name || cubeName;\n      const resolvedSymbol =\n        cubeEvaluator.resolveSymbol(\n          cubeName,\n          name","sourceCodeStart":3691,"sourceCodeEnd":3727,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js#L3691-L3727","documentation":"Cube requires every cube used in a query that needs primary-key based SQL (e.g. joins, primaryKey measures) to declare at least one primary key. primaryKeyNames() throws this UserError when the cube's primaryKeys config is missing or empty.","triggerScenarios":"Calling primaryKeyNames(cubeName) via query building for a cube whose schema lacks the sql primary key declaration (cube name or alias forms of primary key).","commonSituations":"A cube defined without `primaryKey: true` on any dimension while using joins, countDistinct on FKs, or pre-aggregations requiring PK; typo'd cube/alias name passed to a join lookup.","solutions":["Add `primaryKey: true` to one dimension in the cube's YAML or JS schema","Verify the cubeName passed matches the actual cube (or alias) whose PK you expect","If the cube truly has no natural key, add a surrogate key column (e.g. row id) as primaryKey"],"exampleFix":"// before (YAML)\ncubes:\n  - name: orders\n    sql: SELECT * FROM orders\n    dimensions: # no primaryKey\n      - name: id\n        sql: id\n// after\ncubes:\n  - name: orders\n    sql: SELECT * FROM orders\n    dimensions:\n      - name: id\n        sql: id\n        primaryKey: true","handlingStrategy":"validation","validationCode":"const cube = cubejsApi.meta().cubes.find(c => c.name === cubeName);\nconst hasPk = cube?.dimensions?.some(d => d.primaryKey);\nif (!hasPk) throw new Error(`Cube '${cubeName}' must declare a dimension with primaryKey: true`);","typeGuard":"function cubeHasPrimaryKey(cubeMeta) {\n  return Array.isArray(cubeMeta?.dimensions) && cubeMeta.dimensions.some(d => d.primaryKey === true);\n}","tryCatchPattern":"try { await cube.query(query); } catch (e) {\n  if (/Primary key is required for/.test(e.message)) {\n    // prompt user to fix the data model\n  }\n  throw e;\n}","preventionTips":["Always declare primaryKey: true on at least one dimension per cube","Lint data models in CI to assert every cube has a primary key","Check cube name/alias spelling when joins report this error"],"tags":["schema-compiler","primary-key","cube-config"],"backgroundTag":"missing-primary-key","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}