{"record":{"id":"b3d60dae2dc28b3d","repo":"cube-js/cube","slug":"http-response-status-response-statustext","errorCode":null,"errorMessage":"HTTP ${response.status}: ${response.statusText}","messagePattern":"HTTP (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cubejs-client-core/src/HttpTransport.ts","lineNumber":240,"sourceCode":"      setTimeout(() => controller?.abort(), effectiveFetchTimeout);\n    }\n\n    return {\n      stream: async () => {\n        const response = await fetch(url, {\n          method: requestMethod,\n          headers: {\n            Authorization: this.authorization,\n            'x-request-id': baseRequestId || 'stream-request',\n            ...this.headers,\n          } as HeadersInit,\n          credentials: this.credentials,\n          body: requestMethod === 'POST' ? JSON.stringify(params || {}) : null,\n          signal: actualSignal,\n        });\n\n        if (!response.ok) {\n          throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n        }\n\n        if (!response.body) {\n          throw new Error('No response body available for streaming');\n        }\n\n        return responseChunks(response);\n      },\n      unsubscribe: async () => {\n        if (controller) {\n          controller.abort();\n        }\n      },\n    };\n  }\n}\n\nexport default HttpTransport;","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-client-core/src/HttpTransport.ts#L222-L258","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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).","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."],"exampleFix":"// before\nconst cubeApi = cubejs('old-stale-token', { apiUrl: 'https://example.com/cubejs-api/v1' });\nfor await (const row of cubeApi.stream(query)) { ... } // throws 'HTTP 401: Unauthorized'\n\n// after\ntry {\n  for await (const row of cubeApi.stream(query)) { ... }\n} catch (e) {\n  if (/HTTP 40[13]/.test(e.message)) {\n    const token = await refreshToken();\n    const retry = cubejs(token, { apiUrl: 'https://example.com/cubejs-api/v1' });\n    for await (const row of retry.stream(query)) { ... }\n  } else { throw e; }\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight: config errors can be caught before streaming\nif (!apiUrl || !apiUrl.includes('/cubejs-api/v1')) {\n  throw new Error('Cube apiUrl must point to /cubejs-api/v1');\n}\nif (!token) throw new Error('Auth token required before streaming');","typeGuard":"function isOkResponse(res: Response): res is Response & { body: ReadableStream } {\n  return res.ok && res.body != null;\n}","tryCatchPattern":"try {\n  for await (const row of cubeApi.stream(query)) { handle(row); }\n} catch (e) {\n  const m = /^HTTP (\\d{3})/.exec(e.message);\n  if (m && ['401', '403'].includes(m[1])) { await refreshToken(); /* retry once */ }\n  else if (m && m[1].startsWith('5')) { /* retry with backoff */ }\n  else throw e;\n}","preventionTips":["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."],"tags":["network","http","streaming","fetch"],"backgroundTag":"http-non-2xx-response","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}