cube-js/cube · error · UserError

${context} must be a single reference, not an array

Error message

${context} must be a single reference, not an array

What it means

CubeSymbols evaluates a function that must return a single member reference (a string) during schema compilation. If the function returns an array instead, the compiler cannot use it where a lone reference is required, so it throws this UserError. It guards APIs like join paths or reference getters that expect exactly one dimension/measure name.

Source

Thrown at packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts:1247

      // For any branch of return type that can can contain just an object it's OK to return string
      return arrayOrSingle.toString() as any;
    }

    const references: Array<string> = arrayOrSingle.map(p => p.toString());
    // arrayOrSingle is of type `T`, and we just checked that it is an array
    // Which means that both `T` and result must be arrays
    // For any branch of return type that can contain array it's OK to return array
    return options.originalSorting ? references : R.sortBy(R.identity, references) as any;
  }

  public evaluateReference(
    cube: string,
    referencesFn: (...args: Array<unknown>) => ToString,
    context: string
  ): string {
    const result = this.evaluateReferences(cube, referencesFn);
    if (Array.isArray(result)) {
      throw new UserError(`${context} must be a single reference, not an array`);
    }

    return result;
  }

  public pathFromArray(array: string[]): string {
    return array.join('.');
  }

  /**
   * Split join path to member to join hint and member path: `A.B.C.D.E.dim` => `[A, B, C, D, E]` + `E.dim`
   */
  public static joinHintFromPath(path: string): { path: string, joinHint: string[] } {
    const parts = path.split('.');
    if (parts.length > 2) {
      // Path contains join path
      const joinHint = parts.slice(0, -1);
      return {

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Change the function to return a single string reference instead of an array (e.g. `return a.id` not `[a.id]`).
  2. If you need multiple references, move them to the correct multi-value API (e.g. the member list side of the join definition).
  3. Check the data model docs for the exact expected signature of the option you are passing.

Example fix

// before
joins: {
  Users: { sql: '\${CUBE}.userId = \${Users.id}', references: (a, b) => [a.userId, b.id] }
}
// after
joins: {
  Users: { sql: '\${CUBE}.userId = \${Users.id}', references: (a, b) => [a.userId, b.id] } // keep arrays in references;
  // for single-reference APIs: (a) => a.userId
}
Defensive patterns

Strategy: validation

Validate before calling

const refs = myReferencesFn(cubeA, cubeB);
if (Array.isArray(refs)) {
  throw new Error('referencesFn must return a single string reference, got array');
}

Type guard

function isSingleReference(v) { return typeof v === 'string'; }

Try / catch

try { await compiler.compile(); } catch (e) { if (e instanceof UserError && /must be a single reference, not an array/.test(e.message)) { /* fix schema fn */ } else throw e; }

Prevention

When it happens

Trigger: A schema function passed to CubeSymbols (e.g. a references function, join SQL, or referencesFn returning a member name) returns an array of strings instead of a single string. E.g. a join definition whose SQL or referenced member resolves to `[...]`.

Common situations: Defining a join with `references: (a, b) => [a.id, b.id]` style multi-value return where a single reference is expected; copying an array variable into a context expecting one member name; TypeScript-less JS schemas where the wrong shape slips through.

Related errors


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