cube-js/cube · error · UserError
Invalid query format: ${error.message || error.toString()}
Error message
Invalid query format: ${error.message || error.toString()} What it means
The /cubejs-system/v1/sql endpoint validates req.body against cubeSqlRequestSchema (which requires a valid 'query' SQL string among other fields). When Joi validation fails, ApiGateway wraps the Joi error message in this UserError. It means the HTTP request body does not conform to the expected SQL-API request shape.
Source
Thrown at packages/cubejs-api-gateway/src/gateway.ts:557
);
app.post(
`${this.basePath}/v1/cubesql`,
userMiddlewares,
userAsyncHandler(async (req, res) => {
const { query } = req.body;
const requestStarted = new Date();
res.setHeader('Content-Type', 'application/json');
res.setHeader('Transfer-Encoding', 'chunked');
try {
await this.assertApiScope('data', req.context?.securityContext);
const { error, value: body } = cubeSqlRequestSchema.validate(req.body);
if (error) {
throw new UserError(`Invalid query format: ${error.message || error.toString()}`);
}
await this.sqlServer.execSql(body.query, res, req.context?.securityContext, body.cache, body.timezone, body.throwContinueWait, req.context?.requestId);
} catch (e: any) {
// Quickfix for https://github.com/cube-js/cube/issues/10450,
// Right now, it's too complicated to fix the issue correctly, because
// native side control stream, without understanding that it's Express.response
res.removeHeader('Transfer-Encoding');
this.handleError({
e,
query: {
sql: query,
},
context: req.context,
res: this.resToResultFn(res),
requestStarted
});View on GitHub (pinned to 7d981676b3)
Solutions
- Send a body matching the schema: { query: '<SQL string>' } (plus optional cache, timezone, throwContinueWait)
- Read error.message in the response — it echoes the exact Joi validation failure (e.g. '"query" is required') and fix that field
- If using an SDK or ORM integration, verify it targets the SQL API and is up to date
- Log the outgoing req.body and diff it against cubeSqlRequestSchema in packages/cubejs-api-gateway/src
Example fix
// before
await fetch(`${apiUrl}/cubejs-system/v1/sql`, { method: 'POST', body: JSON.stringify({ sql: 'SELECT 1' }) });
// after
await fetch(`${apiUrl}/cubejs-system/v1/sql`, { method: 'POST', body: JSON.stringify({ query: 'SELECT 1' }) }); Defensive patterns
Strategy: validation
Validate before calling
function assertSqlApiBody(body) {
if (!body || typeof body !== 'object') throw new Error('Body must be an object');
if (typeof body.query !== 'string' || !body.query.trim()) throw new Error('"query" (string) is required for the SQL API');
} Type guard
const isSqlApiRequest = (b) => typeof b === 'object' && b !== null && typeof (b).query === 'string' && (b).query.length > 0;
Try / catch
try {
const res = await fetch(`${apiUrl}/cubejs-system/v1/sql`, { method: 'POST', headers: jsonHeaders, body: JSON.stringify({ query }) });
const data = await res.json();
if (data.error && data.error.startsWith('Invalid query format:')) throw new Error(`Fix request body: ${data.error}`);
return data;
} catch (e) {
console.error('SQL API request rejected:', e.message);
throw e;
} Prevention
- Use the official Cube client/SDK instead of hand-rolled fetch calls to this endpoint
- Always send { query: '<sql>' } — the key is 'query', not 'sql' or 'q'
- Set Content-Type: application/json
- Read the echoed Joi message in the error to identify the offending field
When it happens
Trigger: POSTing to the SQL API endpoint with a body missing the 'query' field, a non-string query value, or extra/invalid fields rejected by the schema, e.g. { q: 'SELECT 1' } or { query: 42 } instead of { query: 'SELECT 1' }.
Common situations: Client code built for the REST /load API being pointed at the SQL endpoint with the wrong payload shape; typos in the body key ('sql' vs 'query'); sending GraphQL-style payloads; SDK version mismatch where the request schema changed.
Related errors
- No job description provided
- Query param is required
- Unable to decode query param as JSON, error: ${e.message}
- Can't parse date: '${from}'
- Can't parse date: '${to}'
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/16a18fed4f289bb6.
Report an issue: GitHub.