OtterMind/Chat2DB · error · TypeError

Fetch failed with status ${response.status}

Error message

Fetch failed with status ${response.status}

What it means

sseFetch throws a TypeError when the HTTP response status is not ok (outside 2xx range). This is the response-validation gate for SSE/JSON requests made to the AI streaming endpoint. It fires after fetch resolves but before body parsing, so 4xx/5xx errors from the AI backend surface here. The error includes the numeric status for diagnostics.

Source

Thrown at chat2db-community-client/src/components/SSERequest/sseFetch.ts:56

  }

  /** ---------------------- fetch ---------------------- */
  let response = await fetchFn(...fetchArgs);

  /** ---------------------- response middleware ---------------------- */
  if (typeof middlewares.onResponse === 'function') {
    const modifiedResponse = await middlewares.onResponse(response);

    if (!(modifiedResponse instanceof Response)) {
      throw new TypeError('The options.onResponse must return a Response instance!');
    }

    response = modifiedResponse;
  }

  /** ---------------------- response check ---------------------- */
  if (!response.ok) {
    throw new TypeError(`Fetch failed with status ${response.status}`);
  }

  if (!response.body) {
    throw new TypeError('The response body is empty.');
  }

  /** ---------------------- return ---------------------- */
  return response;
};

export default SSEFetch;

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Inspect response.status in the catch to show a user-appropriate message (auth, rate-limit, server error).
  2. Verify the AI API key and baseURL are correct and current.
  3. Retry with backoff on 429/5xx status codes.
  4. Check backend logs and reverse proxy configuration if status is 502/503.

Example fix

// before
const response = await sseFetch(baseURL, requestInit);

// after
let response;
try {
  response = await sseFetch(baseURL, requestInit);
} catch (e) {
  if (e instanceof TypeError && /Fetch failed with status/.test(e.message)) {
    const status = parseInt(e.message.match(/\d+/)?.[0] || '0', 10);
    showError(status === 429 ? 'Rate limited, try later' : 'AI request failed');
    return;
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Type guard

function isFetchStatusError(e: unknown): e is TypeError {
  return e instanceof TypeError && /Fetch failed with status/.test(e.message);
}

function extractStatus(e: TypeError): number {
  return parseInt(e.message.match(/\d+/)?.[0] || '0', 10);
}

Try / catch

try {
  const response = await sseFetch(baseURL, requestInit);
} catch (e) {
  if (isFetchStatusError(e)) {
    const status = extractStatus(e);
    if (status === 429) return retryWithBackoff();
    if (status === 401) return refreshApiKey();
    onError(`AI request failed (${status})`);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: The AI backend returns HTTP 401 (bad API key), 403 (forbidden), 429 (rate limited), 500 (server error), or 502/503 (upstream down) during an SSE stream POST. Also triggered by a proxy or gateway returning an error HTML page.

Common situations: Expired or invalid AI API key. Rate limiting from the LLM provider. Backend service down or misconfigured reverse proxy. CORS/network errors manifesting as a non-ok status.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/0173baf9c0535870. Report an issue: GitHub.