danielmiessler/Fabric · error · Error
No response from fabric backend
Error message
No response from fabric backend
What it means
Thrown by the /chat endpoint when fabricResponse.ok is true but fabricResponse.body is null/undefined. For a streaming SSE response the body should always be a ReadableStream; a null body with a 200 means the request was made without streaming (e.g. a GET/HEAD-style empty response), the runtime does not expose streaming bodies, or a redirect/204-style response slipped through. It effectively means the proxy cannot pipe Fabric's output to the client.
Source
Thrown at web/src/routes/chat/+server.ts:116
});
console.log('6. Fabric response:', {
status: fabricResponse.status,
ok: fabricResponse.ok,
statusText: fabricResponse.statusText
});
if (!fabricResponse.ok) {
console.error('Error from Fabric API:', {
status: fabricResponse.status,
statusText: fabricResponse.statusText
});
throw new Error(`Fabric API error: ${fabricResponse.statusText}`);
}
const stream = fabricResponse.body;
if (!stream) {
throw new Error('No response from fabric backend');
}
// Create a TransformStream to inspect the data without modifying it
const transformStream = new TransformStream({
transform(chunk, controller) {
const text = new TextDecoder().decode(chunk);
if (text.startsWith('data: ')) {
try {
const data = JSON.parse(text.slice(6));
console.log('Stream chunk format:', {
type: data.type,
format: data.format,
contentLength: data.content?.length
});
} catch (e) {
console.log('Failed to parse stream chunk:', text);
}
}View on GitHub (pinned to 338b89cfe9)
Solutions
- Check the logged Fabric response object — if status is 200 but body is null, replay the same request with curl against the Fabric port to see whether it actually streams
- Ensure the proxied request preserves the streaming method/headers (Accept: text/event-stream) that Fabric requires
- Verify the SvelteKit adapter supports streaming responses (node adapter does; some serverless previews do not)
- Upgrade/hot-restart the Fabric server if it is returning empty 200s; check its logs for mid-stream aborts
Example fix
// before
const stream = fabricResponse.body;
if (!stream) {
throw new Error('No response from fabric backend');
}
// after
const stream = fabricResponse.body;
if (!stream) {
// Distinguish 'backend returned nothing' from 'streaming unsupported here'
const text = await fabricResponse.text().catch(() => '');
throw error(502, text
? `Fabric backend returned a non-streaming response: ${text.slice(0, 200)}`
: 'No response body from fabric backend');
} Defensive patterns
Strategy: type-guard
Validate before calling
// Confirm streaming is supported in this runtime before proxying
if (typeof ReadableStream === 'undefined' || !('body' in Response.prototype)) {
throw error(500, 'Streaming responses unsupported by this adapter');
} Type guard
function hasBody(r: Response): r is Response & { body: ReadableStream<Uint8Array> } {
return r.ok && r.body instanceof ReadableStream;
}
// usage
if (!hasBody(fabricResponse)) {
const text = await fabricResponse.text().catch(() => '');
throw error(502, text || 'No response from fabric backend');
} Try / catch
try {
if (!hasBody(fabricResponse)) throw error(502, 'No response from fabric backend');
return new Response(fabricResponse.body.pipeThrough(transformStream), {
headers: { 'Content-Type': 'text/event-stream' }
});
} catch (e) {
console.error('Fabric streaming failed:', e);
throw error(502, 'Fabric stream unavailable');
} Prevention
- Use a runtime/adapter with ReadableStream support for SSE proxying (node adapter, not static/serverless previews)
- Pass through Accept: text/event-stream so Fabric actually streams
- narrow with an instanceof ReadableStream guard instead of a truthiness check to also catch body-already-consumed cases
When it happens
Trigger: Fabric backend returning 200 with an empty body (pattern produced no output), a fetch that followed a redirect to a non-streaming response, running under a runtime/adapter where response.body is not implemented, or the request to Fabric missing the streaming headers Fabric expects so it returns an empty 200.
Common situations: SvelteKit adapter or preview environment without full streaming support, Fabric version that closed the stream before writing anything, middleware (compression/proxy) that consumed or stripped the body before the handler read it.
Related errors
- HTTP error! status: ${response.status}
- Response body is null
- HTTP_ERROR
- NULL_RESPONSE
- STREAM_CONTENT_ERROR
AI-assisted analysis of danielmiessler/Fabric@338b89cfe9 (2026-08-15).
Data as JSON: /api/errors/0bc6947dd6f7e988.
Report an issue: GitHub.