cube-js/cube · error · UserError
No job description provided
Error message
No job description provided
What it means
The pre-aggregations jobs endpoint (/cubejs-system/v1/pre_aggregations/jobs) requires a non-empty JSON body describing the job (e.g. action, preAggregations list). If req.body is missing or an empty object, ApiGateway throws this UserError before even running schema validation, because there is no job description to act on.
Source
Thrown at packages/cubejs-api-gateway/src/gateway.ts:1062
* "ec1232ea3356f04f8be313fecf3deb4d",
* "48b75d5c466fa579c936dc451f498f69",
* "76509837091396dc204abb1016c48e75",
* "52264769f81f6ff62062a93d6f6fbdb2"
* ]
* }
* ```
*/
private async preAggregationsJobs(req: Request, res: ExpressResponse) {
const response = this.resToResultFn(res);
const requestStarted = new Date();
const context = <RequestContext>req.context;
const query = <PreAggsJobsRequest>req.body;
let result;
try {
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.'
);View on GitHub (pinned to 7d981676b3)
Solutions
- Send a JSON body matching preAggsJobsRequestSchema, e.g. { action: 'post', preAggregations: [{ tableName: 'orders_main' }] }
- Set the Content-Type: application/json header so the body parser populates req.body
- Check for typos: an incorrectly keyed payload may deserialize to an object the schema later rejects — the 'No job description provided' case is specifically empty/missing body
- Verify with curl -v or network tab that a non-empty body is actually transmitted
Example fix
// before
await fetch(`${apiUrl}/cubejs-system/v1/pre_aggregations/jobs`, { method: 'POST', headers: { authorization: token } });
// after
await fetch(`${apiUrl}/cubejs-system/v1/pre_aggregations/jobs`, { method: 'POST', headers: { authorization: token, 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'post', preAggregations: [{ tableName: 'orders_main' }] }) }); Defensive patterns
Strategy: validation
Validate before calling
function assertJobsBody(body) {
if (!body || Object.keys(body).length === 0) throw new Error('pre_aggregations/jobs requires a non-empty JSON body, e.g. { action: "post", preAggregations: [...] }');
} Type guard
const hasJobDescription = (b) => typeof b === 'object' && b !== null && Object.keys(b).length > 0;
Try / catch
try {
const res = await fetch(`${apiUrl}/cubejs-system/v1/pre_aggregations/jobs`, { method: 'POST', headers: jsonHeaders, body: JSON.stringify(jobsRequest) });
const data = await res.json();
if (data.error === 'No job description provided') throw new Error('Jobs endpoint got an empty body — check payload serialization');
return data;
} catch (e) {
console.error('Pre-aggs jobs call failed:', e.message);
throw e;
} Prevention
- Always send a non-empty JSON body with action and preAggregations fields
- Set Content-Type: application/json — without it req.body may parse to {}
- Verify the payload with JSON.stringify before the call (empty objects serialize to '{}')
- Don't fire-and-forget empty POSTs (e.g. health checks) at this endpoint
When it happens
Trigger: POSTing to the pre-aggs jobs endpoint with no body, body: {}, or a body that serializes to {} (e.g. Content-Type not application/json so the body parser yields an empty object), instead of e.g. { action: 'post', preAggregations: [...] }.
Common situations: Forgetting to send a JSON body in fetch/axios calls; missing Content-Type: application/json header so the body parses empty; empty POST health-check pings hitting the jobs endpoint; copy-pasted requests that dropped the payload.
Related errors
- Invalid query format: ${error.message || error.toString()}
- Invalid Job query format: ${error.message || error.toString(
- A user's selector doesn't match any of the pre-aggregations
- The '${query.action}' action type doesn't supported.
- Cannot parse selector date range ${selector.dateRange}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/13b95ac71f502019.
Report an issue: GitHub.