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
- 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`.
- Check `selector.dataSources` matches the dataSource keys defined in your `dbType`/`dataSource` configuration (default is 'default').
- Remove or correct entries in `selector.cubes`/`selector.preAggregations` that no longer exist in the data model.
- Confirm the security context used for the request can see the targeted cubes (multi-tenant setups may hide them).
- 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
- Always source cube/pre-aggregation names from the /meta endpoint instead of hardcoding them.
- Use the exact `CubeName.PreAggregationName` format in selector.preAggregations.
- Verify dataSource names in multi-database deployments (default is 'default').
- Add a CI check that selector constants in refresh scripts still exist in the current data model.
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
- No job description provided
- Invalid Job query format: ${error.message || error.toString(
- The '${query.action}' action type doesn't supported.
- Cannot parse selector date range ${selector.dateRange}
- Can't refresh pre-aggregation without measures and dimension
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/09b0abaf7b15642f.
Report an issue: GitHub.