continuedev/continue · error · Error
non-200 response body: ${await response.text()}
Error message
non-200 response body: ${await response.text()} What it means
streamResponse throws the response body text when the HTTP status is not 200 (and not 499, which signals client cancellation and returns silently). The body text typically carries the server's error message.
Source
Thrown at packages/fetch/src/stream.ts:18
export async function* toAsyncIterable(
nodeReadable: NodeJS.ReadableStream,
): AsyncGenerator<Uint8Array> {
for await (const chunk of nodeReadable) {
// @ts-ignore
yield chunk as Uint8Array;
}
}
export async function* streamResponse(
response: Response,
): AsyncGenerator<string> {
if (response.status === 499) {
return; // In case of client-side cancellation, just return
}
if (response.status !== 200) {
throw new Error(await response.text());
}
if (!response.body) {
throw new Error("No response body returned.");
}
// Get the major version of Node.js
const nodeMajorVersion = parseInt(process.versions.node.split(".")[0], 10);
let chunks = 0;
try {
if (nodeMajorVersion >= 20) {
// Use the new API for Node 20 and above
const stream = (ReadableStream as any).from(response.body);
for await (const chunk of stream.pipeThrough(
new TextDecoderStream("utf-8"),
)) {
yield chunk;View on GitHub (pinned to 5522c6f44c)
Solutions
- Inspect status before streaming: if (response.status !== 200) handle error with status and body
- Fix auth/endpoint issues indicated by the status code (401 → API key, 429 → backoff, 404 → URL)
- Retry with exponential backoff for 429/5xx
- Log response.headers like 'x-ratelimit-*' to diagnose limits
Example fix
// before
const stream = streamSse(response);
// after
if (response.status !== 200) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const stream = streamSse(response); Defensive patterns
Strategy: try-catch
Validate before calling
if (response.status !== 200) { const text = await response.text(); throw Object.assign(new Error(text), { status: response.status }); } Try / catch
try { for await (const c of streamSse(response)) {} } catch (e) { if (e.message.includes('status')) {} /* handle */ } Prevention
- Check response.status before passing to streamSse/streamJSON
- Centralize status→error mapping with retry/backoff for 429/5xx
- Refresh auth tokens on 401
When it happens
Trigger: Any streamed request (streamSse/streamJSON) whose response has status 400/401/403/404/429/500 etc.; the awaited response.text() becomes the error message.
Common situations: Expired or wrong API keys (401), hitting rate limits (429), wrong endpoint paths (404), or upstream server errors (500) during chat completion streaming.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Stream was closed before any data was received. Try again. (
- The response was cancelled mid-stream. Try again. (Premature
- No response body returned.
- Error streaming response: ${data.error.message}
- Error streaming response: ${JSON.stringify(data.error)}
AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27).
Data as JSON: /api/errors/202281a1ebc1b2e0.
Report an issue: GitHub.