cube-js/cube · error · UserError

One or more Primary key is required for '${cubeName}' cube

Error message

One or more Primary key is required for '${cubeName}' cube

What it means

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.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:3709

  }

  autoPrefixAndEvaluateSql(cubeName, sql, isMemberExpr = false) {
    return this.autoPrefixWithCubeName(cubeName, this.evaluateSql(cubeName, sql), isMemberExpr);
  }

  concatStringsSql(strings) {
    return strings.join(' || ');
  }

  /**
   *
   * @param {string} cubeName
   * @returns {Array<string>}
   */
  primaryKeyNames(cubeName) {
    const primaryKeys = this.cubeEvaluator.primaryKeys[cubeName];
    if (!primaryKeys || !primaryKeys.length) {
      throw new UserError(`One or more Primary key is required for '${cubeName}' cube`);
    }
    return primaryKeys.map((pk) => this.primaryKeyName(cubeName, pk));
  }

  primaryKeyName(cubeName, primaryKey) {
    return `${cubeName}.${primaryKey}`;
  }

  evaluateSql(cubeName, sql, options) {
    options = options || {};
    const self = this;
    const { cubeEvaluator } = this;
    return cubeEvaluator.resolveSymbolsCall(sql, (name) => {
      const nextCubeName = cubeEvaluator.symbols[name] && name || cubeName;
      const resolvedSymbol =
        cubeEvaluator.resolveSymbol(
          cubeName,
          name

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Add `primaryKey: true` to one dimension in the cube's YAML or JS schema
  2. Verify the cubeName passed matches the actual cube (or alias) whose PK you expect
  3. If the cube truly has no natural key, add a surrogate key column (e.g. row id) as primaryKey

Example fix

// before (YAML)
cubes:
  - name: orders
    sql: SELECT * FROM orders
    dimensions: # no primaryKey
      - name: id
        sql: id
// after
cubes:
  - name: orders
    sql: SELECT * FROM orders
    dimensions:
      - name: id
        sql: id
        primaryKey: true
Defensive patterns

Strategy: validation

Validate before calling

const cube = cubejsApi.meta().cubes.find(c => c.name === cubeName);
const hasPk = cube?.dimensions?.some(d => d.primaryKey);
if (!hasPk) throw new Error(`Cube '${cubeName}' must declare a dimension with primaryKey: true`);

Type guard

function cubeHasPrimaryKey(cubeMeta) {
  return Array.isArray(cubeMeta?.dimensions) && cubeMeta.dimensions.some(d => d.primaryKey === true);
}

Try / catch

try { await cube.query(query); } catch (e) {
  if (/Primary key is required for/.test(e.message)) {
    // prompt user to fix the data model
  }
  throw e;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/76ef407f8c01edbf. Report an issue: GitHub.