danielmiessler/Fabric · error · Error
HTTP error! status: ${response.status}
Error message
HTTP error! status: ${response.status} What it means
Thrown by the generic api.stream() helper in web/src/lib/api/base.ts when a streaming POST to /api<endpoint> returns a non-2xx status. The helper only checks response.ok before trying to acquire a reader, so any HTTP-level failure (404, 500, 503) surfaces as this generic error with only the numeric status attached. It does not attempt to read the response body, so any server error detail is lost.
Source
Thrown at web/src/lib/api/base.ts:43
}
return { data: await response.json() as T };
},
get: <T>(endpoint: string) => api.fetch<T>(endpoint),
post: <T>(endpoint: string, data: unknown) => api.fetch<T>(endpoint, { method: 'POST', body: JSON.stringify(data) }),
put: <T>(endpoint: string, data?: unknown) => api.fetch<T>(endpoint, { method: 'PUT', body: data ? JSON.stringify(data) : undefined }),
delete: <T>(endpoint: string) => api.fetch<T>(endpoint, { method: 'DELETE' }),
stream: async function* (endpoint: string, data: unknown): AsyncGenerator<string> {
const response = await fetch(`/api${endpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body?.getReader();
if (!reader) throw new Error('Response body is null');
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
yield decoder.decode(value);
if (done) break;
}
}
};
export function createStorageAPI<T extends StorageEntity>(entityType: string) {
return {
async get(name: string): Promise<T> {View on GitHub (pinned to 338b89cfe9)
Solutions
- Check which status code is embedded in the message, then reproduce the same POST with curl to see the server's error body
- If 404, verify the endpoint path and that the backend registers the matching /api route
- If 5xx, inspect backend logs for the panic/error behind the failed streaming call
- Improve the throw site to read response.text() before throwing so server detail is preserved
Example fix
// before
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// after
if (!response.ok) {
const detail = await response.text().catch(() => '');
throw new Error(`HTTP ${response.status} on ${endpoint}: ${detail || 'no body'}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the endpoint exists before streaming
const probe = await fetch(`/api${endpoint}`, { method: 'HEAD' }).catch(() => null);
if (!probe?.ok) {
throw new Error(`Endpoint /api${endpoint} not ready (HEAD ${probe?.status ?? 'unreachable'})`);
} Type guard
function isHttpStreamError(e: unknown, status?: number): boolean {
return e instanceof Error && /HTTP error! status/.test(e.message)
&& (status === undefined || e.message.includes(String(status)));
} Try / catch
try {
for await (const chunk of api.stream('/chat', payload)) { /* ... */ }
} catch (e) {
if (isHttpStreamError(e)) { /* surface status, stop retrying 4xx */ }
else throw e;
} Prevention
- Health-check the backend before starting a stream
- Include the endpoint name in thrown errors at the call site for fast triage
- Never retry 4xx statuses; only retry 5xx with backoff
When it happens
Trigger: Any call to api.stream(endpoint, data) where the server replies non-OK: unknown route under /api (404), backend down or proxy misrouted (502/503), malformed JSON body causing a 400, or an auth/session expiry returning 401.
Common situations: Dev server proxy not forwarding the /api prefix to the backend; backend handler panicked mid-request; sending a payload the endpoint rejects; running the frontend against a stale backend that lacks the route.
Related errors
- HTTP_ERROR
- errorData.error || `HTTP error! status: ${response.status}`
- await response.text()
- Failed to load session: ${response.statusText}
- Fabric API error: ${fabricResponse.statusText}
AI-assisted analysis of danielmiessler/Fabric@338b89cfe9 (2026-08-15).
Data as JSON: /api/errors/09f760a1199bd596.
Report an issue: GitHub.