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
- 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.
- Catch the error where you consume the stream (await stream()), refresh the token if 401, and retry once.
- Verify the endpoint works with curl using the same headers (Authorization, Content-Type).
- 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
- Parse the 'HTTP <code>' message prefix for alerting and status-specific handling.
- Refresh auth tokens proactively before they expire rather than relying on 401 recovery.
- Validate query names (cubes/measures/dimensions) against your data model before sending.
- Verify apiUrl matches the deployed Cube endpoint including the /cubejs-api/v1 prefix.
- Send x-request-id and correlate with Cube server logs when diagnosing 5xx.
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
- unexpected response ${response.statusText}
- HTTP error! status: ${response.status}
- Unexpected stream end before row with types
- Stream query failed: ${e}; query id: ${queryId}
- No response body available for streaming
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/b3d60dae2dc28b3d.
Report an issue: GitHub.