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

  1. Send a body matching the schema: { query: '<SQL string>' } (plus optional cache, timezone, throwContinueWait)
  2. Read error.message in the response — it echoes the exact Joi validation failure (e.g. '"query" is required') and fix that field
  3. If using an SDK or ORM integration, verify it targets the SQL API and is up to date
  4. 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

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


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