cube-js/cube · error · CubejsHandlerError
Invalid message format
Error message
Invalid message format
What it means
Any WebSocket message that is neither an authorization nor an unsubscribe message falls through to methodMessageSchema, which requires a valid 'method' field (one of the supported methods) plus method-specific payload. Zod failure throws CubejsHandlerError(400, 'Invalid message format') with a detail naming the missing/invalid field.
Source
Thrown at packages/cubejs-api-gateway/src/ws/subscription-server.ts:86
if (!result.success) {
throw new CubejsHandlerError(400, 'Invalid authorization message format', this.mapZodError(result.error));
}
return result.data;
}
if ('unsubscribe' in message) {
const result = unsubscribeMessageSchema.safeParse(message);
if (!result.success) {
throw new CubejsHandlerError(400, 'Invalid unsubscribe message format', this.mapZodError(result.error));
}
return result.data;
}
const result = methodMessageSchema.safeParse(message);
if (!result.success) {
throw new CubejsHandlerError(400, 'Invalid message format', this.mapZodError(result.error));
}
return result.data;
}
public async processMessage(connectionId: string, body: string) {
let message: any | undefined;
try {
message = this.deserializeMessage(body);
message = this.validateMessage(message);
await this.handleMessage(connectionId, message, false);
} catch (e) {
this.apiGateway.handleError({
e,
query: message?.query,
res: this.resultFn(connectionId, message?.messageId, undefined, false),View on GitHub (pinned to 7d981676b3)
Solutions
- Send { messageId: '<id>', method: 'load'|'subscribe'|..., <methodPayload> } exactly as the schema requires; check methodMessageSchema for the version in use.
- Read the Zod detail after the error message to identify the exact missing/invalid field.
- Use @cubejs-client/core with the WebSocket transport instead of raw protocol messages.
Example fix
// before
socket.send(JSON.stringify({ method: 'fetch', query: {} }));
// after
socket.send(JSON.stringify({ messageId: '1', method: 'load', query: { measures: ['Orders.count'] } })); Defensive patterns
Strategy: validation
Validate before calling
function isValidMethodMessage(msg: unknown): boolean {
const m = msg as any;
const METHODS = ['load', 'subscribe'];
return typeof m === 'object' && m !== null &&
typeof m.messageId === 'string' &&
METHODS.includes(m.method);
} Type guard
function isMethodMessage(m: unknown): m is { messageId: string, method: 'load' | 'subscribe', [k: string]: unknown } {
return typeof m === 'object' && m !== null && typeof (m as any).method === 'string';
} Try / catch
try {
await handleMessage(frame);
} catch (e) {
if (e.status === 400 && e.error === 'Invalid message format') {
console.error('Method frame rejected:', e.message); // Zod path/message details
} else throw e;
} Prevention
- Use @cubejs-client/core with WebSocketTransport instead of hand-rolled WS protocol calls.
- Always include messageId and a valid method name per methodMessageSchema.
- Validate the outgoing object against the schema locally in tests.
- Keep client and server versions in sync to avoid protocol drift.
When it happens
Trigger: Sending { ... } without a recognized method, misspelling it (e.g. 'Load' vs 'load'), omitting required fields like messageId or query, or including only unknown properties.
Common situations: Custom WS integrations guessing the protocol; sending REST-style payloads over WS; sending ping/heartbeat frames as regular messages; old client library talking to a newer server schema (or vice versa).
Related errors
- Invalid authorization message format
- Invalid unsubscribe message format
- messageId is required
- Method is required
- Invalid JSON payload
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/0f00eda7758a7d67.
Report an issue: GitHub.