cube-js/cube · error

HTTP ${response.status}: ${response.statusText}

Error message

HTTP ${response.status}: ${response.statusText}

What it means

HttpTransport.requestStream() performs a fetch to the Cube REST API and, before handing the response to the streaming reader (responseChunks), checks response.ok. If the server returned a non-2xx status (401 unauthorized, 400 bad request, 404 wrong URL, 500 server error, etc.), it throws an Error containing the HTTP status code and status text. It is the streaming equivalent of the regular request error path: the API call itself failed before any data could be streamed.

Source

Thrown at packages/cubejs-client-core/src/HttpTransport.ts:240

      setTimeout(() => controller?.abort(), effectiveFetchTimeout);
    }

    return {
      stream: async () => {
        const response = await fetch(url, {
          method: requestMethod,
          headers: {
            Authorization: this.authorization,
            'x-request-id': baseRequestId || 'stream-request',
            ...this.headers,
          } as HeadersInit,
          credentials: this.credentials,
          body: requestMethod === 'POST' ? JSON.stringify(params || {}) : null,
          signal: actualSignal,
        });

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        if (!response.body) {
          throw new Error('No response body available for streaming');
        }

        return responseChunks(response);
      },
      unsubscribe: async () => {
        if (controller) {
          controller.abort();
        }
      },
    };
  }
}

export default HttpTransport;

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Read the status code in the message: 401/403 -> refresh or fix the auth token; 400 -> validate the query (cube/measure/dimension names, timeDimensions); 404 -> fix apiUrl in the CubeApi constructor; 5xx -> check Cube server logs.
  2. Catch the error where you consume the stream (await stream()), refresh the token if 401, and retry once.
  3. Verify the endpoint works with curl using the same headers (Authorization, Content-Type).
  4. Ensure the deployed Cube version supports the streaming API for that route.

Example fix

// before
const cubeApi = cubejs('old-stale-token', { apiUrl: 'https://example.com/cubejs-api/v1' });
for await (const row of cubeApi.stream(query)) { ... } // throws 'HTTP 401: Unauthorized'

// after
try {
  for await (const row of cubeApi.stream(query)) { ... }
} catch (e) {
  if (/HTTP 40[13]/.test(e.message)) {
    const token = await refreshToken();
    const retry = cubejs(token, { apiUrl: 'https://example.com/cubejs-api/v1' });
    for await (const row of retry.stream(query)) { ... }
  } else { throw e; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: config errors can be caught before streaming
if (!apiUrl || !apiUrl.includes('/cubejs-api/v1')) {
  throw new Error('Cube apiUrl must point to /cubejs-api/v1');
}
if (!token) throw new Error('Auth token required before streaming');

Type guard

function isOkResponse(res: Response): res is Response & { body: ReadableStream } {
  return res.ok && res.body != null;
}

Try / catch

try {
  for await (const row of cubeApi.stream(query)) { handle(row); }
} catch (e) {
  const m = /^HTTP (\d{3})/.exec(e.message);
  if (m && ['401', '403'].includes(m[1])) { await refreshToken(); /* retry once */ }
  else if (m && m[1].startsWith('5')) { /* retry with backoff */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling requestStream (used internally by cubeApi.stream()) when the server responds with a non-OK HTTP status: expired/invalid JWT in the Authorization header, malformed query yielding 400, incorrect apiUrl path yielding 404, or 5xx from the Cube backend. The message contains the exact status, e.g. 'HTTP 401: Unauthorized'.

Common situations: Token expired mid-session so /cubejs-api/v1/load returns 401; query references a non-existent cube/measure producing 400 or 500; apiUri misconfigured (wrong port or missing /cubejs-api/v1) producing 404; backend restart producing 502/503 behind a proxy; long-running query aborted by a gateway timeout (504).

Related errors


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