cube-js/cube · error · UserError

A user's selector doesn't match any of the pre-aggregations

Error message

A user's selector doesn't match any of the pre-aggregations defined in the data model.

What it means

After a successful 'post' action on the pre-aggregations jobs API, the gateway checks the list of created build jobs. If `preAggregationsJobsPOST` returned an empty array — meaning the selector matched zero pre-aggregations in the compiled data model — this UserError is thrown. It indicates the request was well-formed but nothing in the data model corresponds to the cubes/preAggregations/dataSources you selected.

Source

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

      await this.assertApiScope('jobs', req?.context?.securityContext);

      if (!query || Object.keys(query).length === 0) {
        throw new UserError('No job description provided');
      }

      const { error, value } = preAggsJobsRequestSchema.validate(query);
      if (error) {
        throw new UserError(`Invalid Job query format: ${error.message || error.toString()}`);
      }

      switch (query.action) {
        case 'post':
          result = await this.preAggregationsJobsPOST(
            context,
            <PreAggsSelector>value.selector
          );
          if (result.length === 0) {
            throw new UserError(
              'A user\'s selector doesn\'t match any of the ' +
              'pre-aggregations defined in the data model.'
            );
          }
          break;
        case 'get':
          result = await this.preAggregationsJobsGET(
            context,
            <string[]>query.tokens,
            query.resType,
          );
          break;
        default:
          throw new Error(`The '${query.action}' action type doesn't supported.`);
      }
      this.event(`pre_aggregations_jobs_${query.action}`, {
        source: req.header('source') || 'unknown',
      });

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the exact cube and pre-aggregation names via the metadata API (`GET /cubejs-system/v1/meta`) and use the `CubeName.PreAggregationName` format in `selector.preAggregations`.
  2. Check `selector.dataSources` matches the dataSource keys defined in your `dbType`/`dataSource` configuration (default is 'default').
  3. Remove or correct entries in `selector.cubes`/`selector.preAggregations` that no longer exist in the data model.
  4. Confirm the security context used for the request can see the targeted cubes (multi-tenant setups may hide them).
  5. If pre-aggregations are conditionally defined (e.g., only when `refreshKey` conditions hold), check the compiler logs to see what pre-aggregations were actually compiled.

Example fix

// before
{ "action": "post", "selector": { "preAggregations": ["Event.Main"] } }

// after (name fixed to match the data model)
{ "action": "post", "selector": { "cubes": ["Events"], "preAggregations": ["Events.Main"], "timezones": ["UTC"] } }
Defensive patterns

Strategy: validation

Validate before calling

async function assertSelectorMatches(metaUrl, headers, selector) {
  const meta = await (await fetch(metaUrl, { headers })).json();
  const allPreAggs = new Set(
    meta.cubes.flatMap(c => (c.preAggregations || []).map(p => `${c.name}.${p.name}`))
  );
  const wanted = selector.preAggregations?.length ? selector.preAggregations : [...allPreAggs];
  const missing = wanted.filter(name => !allPreAggs.has(name));
  if (wanted.length === 0 || missing.length) {
    throw new Error(`Selector matches no pre-aggregations; unknown: ${missing.join(', ')}`);
  }
}

Type guard

function isNonEmptySelector(s: unknown): s is { cubes?: string[]; preAggregations?: string[]; dataSources?: string[]; contexts?: unknown[]; timezones?: string[] } {
  return !!s && typeof s === 'object' &&
    (Object.keys(s).length > 0);
}

Try / catch

try {
  const jobs = await postPreAggJobs({ action: 'post', selector });
} catch (e) {
  if (String(e.message).includes("doesn't match any of the pre-aggregations")) {
    // refresh /meta and reconcile selector names before retrying
    console.error('No pre-aggregations matched selector; check names/dataSources');
  }
}

Prevention

When it happens

Trigger: POST to `/cubejs-system/v1/pre-aggregations/jobs` with `action: 'post'` where the `selector` references cube names, pre-aggregation names (in `Cube.Name` form), or dataSources that don't exist in the current data model — the compiler's `preAggregations()` lookup returns zero entries, so no jobs are queued.

Common situations: Typos in cube or pre-aggregation names; referencing pre-aggregations that were renamed or removed from the schema; wrong `dataSource` name in multi-database setups; stale selectors hardcoded in refresh-automation scripts after a data-model refactor; pre-aggregations exist but are filtered out by security context or data source scoping.

Related errors


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