cube-js/cube · error

A user-defined contextToApiScopes function returns a wrong s

Error message

A user-defined contextToApiScopes function returns a wrong scope: ${p}

What it means

After confirming contextToApiScopes returns an array, Cube validates every element against the allowed scopes: 'graphql', 'meta', 'data', 'sql', 'jobs'. If the function returns an array containing any other string, this Error names the offending scope.

Source

Thrown at packages/cubejs-api-gateway/src/gateway.ts:2788

  protected createContextToApiScopesFn(
    options: ApiGatewayOptions,
  ): ContextToApiScopesFn {
    return options.contextToApiScopes
      ? async (securityContext?: any, defaultApiScopes?: ApiScopes[]) => {
        const scopes = options.contextToApiScopes &&
            await options.contextToApiScopes(
              securityContext,
              defaultApiScopes,
            );
        if (!scopes || !Array.isArray(scopes)) {
          throw new Error(
            'A user-defined contextToApiScopes function returns an inconsistent type.'
          );
        } else {
          scopes.forEach((p) => {
            if (['graphql', 'meta', 'data', 'sql', 'jobs'].indexOf(p) === -1) {
              throw new Error(
                `A user-defined contextToApiScopes function returns a wrong scope: ${p}`
              );
            }
          });
        }
        return scopes;
      }
      : async () => {
        const defaultApiScope = getEnv('defaultApiScope');
        if (defaultApiScope) {
          return defaultApiScope;
        } else {
          return this.contextToApiScopesDefFn();
        }
      };
  }

  protected async assertApiScope(

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Map your application roles onto the exact supported scopes: 'graphql', 'meta', 'data', 'sql', 'jobs'.
  2. Fix typos in scope names returned by the function (compare against the error message's offending value).
  3. Introduce an explicit role→scopes mapping object in your config instead of passing raw role strings.
  4. Add a unit test for contextToApiScopes asserting outputs are subsets of the allowed list.

Example fix

// before
contextToApiScopes: (ctx) => [ctx.role], // 'admin'
// after
contextToApiScopes: (ctx) => ctx.role === 'admin'
  ? ['graphql', 'meta', 'data', 'sql', 'jobs']
  : ['data'],
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['graphql', 'meta', 'data', 'sql', 'jobs'];
function validateScopes(scopes) {
  if (!Array.isArray(scopes)) throw new TypeError('must be array');
  const bad = scopes.filter(s => !ALLOWED.includes(s));
  if (bad.length) throw new Error(`Unknown scopes: ${bad.join(', ')}`);
  return scopes;
}

Type guard

const isApiScope = (s) => ['graphql','meta','data','sql','jobs'].includes(s);
function areValidScopes(v) {
  return Array.isArray(v) && v.every(isApiScope);
}

Try / catch

try {
  await cubeApi.load(query);
} catch (e) {
  if (/wrong scope/.test(e.message)) {
    // fix the scope mapping in server config using the offending value in the message
  }
  throw e;
}

Prevention

When it happens

Trigger: A custom contextToApiScopes returning values like 'read', 'write', 'admin', 'all', or pluralized/typo'd names ('datas', 'metas') that are not among the five permitted scope strings.

Common situations: Mapping app-level permissions/roles directly into scopes without translating them to Cube's scope vocabulary; inventing custom scopes expecting them to be honored; typos after upgrading Cube where the allowed list differs from what an old example showed.

Related errors


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