cube-js/cube · error · MessageTooLargeError

Cube Store response size exceeds the maximum message size of

Error message

Cube Store response size exceeds the maximum message size of ${formatSize(this.maxMessageSize)}. Reduce the amount of data the query returns, e.g. by adding filters or a limit, or raise CUBEJS_CUBESTORE_MAX_MESSAGE_SIZE.

What it means

The Cube Store WebSocket driver rejects responses whose serialized size exceeds the client limit CUBEJS_CUBESTORE_MAX_MESSAGE_SIZE. Instead of failing the reconnect loop, it sets a fatalError (MessageTooLargeError) on the socket because retrying would return the same oversized response.

Source

Thrown at packages/cubejs-cubestore-driver/src/WebSocketConnection.ts:195

              // failing it here would surface a spurious `write EPIPE` for a
              // query that never reached Cube Store.
              webSocket.terminate();
            }

            resolveSend();
          });
        });
        webSocket.on('open', () => resolve(webSocket));
        webSocket.on('error', (err) => {
          if ((err as any).code === MAX_PAYLOAD_EXCEEDED_CODE) {
            // Cube Store answered with a message bigger than this connection
            // accepts, and `ws` is tearing the connection down. Neither
            // reconnecting nor retrying the query helps: the response would be
            // just as big. Pending messages are rejected by the 'close' handler.
            webSocket.fatalError = new MessageTooLargeError(
              `Cube Store response size exceeds the maximum message size of ${formatSize(this.maxMessageSize)}. ` +
              'Reduce the amount of data the query returns, e.g. by adding filters or a limit, ' +
              'or raise CUBEJS_CUBESTORE_MAX_MESSAGE_SIZE.',
              err
            );

            if (webSocket === this.webSocket) {
              this.webSocket = null;
            }

            // No-op if the connection was already established.
            reject(webSocket.fatalError);

            return;
          }

          // The socket is done either way, so stop its heartbeat now rather than
          // relying on a 'close' that may not follow: the interval is what keeps
          // the socket, and everything reachable from it, alive.
          webSocket.teardown();

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Reduce returned data: add filters, time dimensions, or a row limit to the query.
  2. Aggregate in Cube (pre-aggregations, rollups) instead of returning raw rows.
  3. Raise CUBEJS_CUBESTORE_MAX_MESSAGE_SIZE (and the matching Cube Store side limits) if the payload is genuinely needed.

Example fix

// before
const rs = await cube.query({ measures: ['Orders.count'], dimensions: ['Orders.id'] });
// after
const rs = await cube.query({ measures: ['Orders.count'], dimensions: ['Orders.status'], limit: 10000 });
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const rs = await connection.query(query);
} catch (e) {
  if (e instanceof MessageTooLargeError) {
    // shrink query (filters/limit) or raise CUBEJS_CUBESTORE_MAX_MESSAGE_SIZE
  }
  throw e;
}

Prevention

When it happens

Trigger: A query returns a result frame larger than maxMessageSize when read off the WebSocket from Cube Store — typically huge result sets or large pre-aggregation downloads.

Common situations: Unaggregated queries returning millions of rows, pulling large arrays/measures without limit, small CUBEJS_CUBESTORE_MAX_MESSAGE_SIZE relative to dataset.

Related errors


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