denoland/deno · error · TypeError
Invalid response
Error message
Invalid response
What it means
Thrown by fastSyncResponseOrStream when a handler's Response body reached the final dispatch branch but its internal streamOrStatic value is not a ReadableStream. The function already handled null/undefined, static strings, and Uint8Array bodies, so hitting this check means the Response object did not come from a genuine in-realm Response constructor (mock, polyfill, or cross-realm instance) or its internal InnerBody was abnormal. The request is closed and the error is routed through onError, so clients see a 500 if it is unhandled.
Solutions
- Return only Responses built by the runtime's global Response constructor
- Re-wrap foreign Responses at the boundary: `return new Response(foreign.body, foreign)`
- Remove packages that overwrite globalThis.Response, or configure the bundler to not polyfill fetch in Deno builds
- Build bodies only from null, string, Uint8Array, Blob, or ReadableStream
Example fix
// before
import { Response as UndiciResponse } from 'undici';
Deno.serve(() => fetchViaUndici()); // returns undici Response -> Invalid response
// after
Deno.serve(async () => {
const foreign = await fetchViaUndici();
return new Response(foreign.body, foreign); // native Response, stream body passes
}); Defensive patterns
Strategy: validation
Validate before calling
// Before returning anything that might be foreign, verify the body type:
const body = candidate.body;
if (
body !== null &&
typeof body !== 'string' &&
!(body instanceof Uint8Array) &&
!(body instanceof Blob) &&
!(body instanceof ReadableStream)
) {
throw new Error(`Unsupported response body: ${Object.prototype.toString.call(body)}`);
}
return candidate instanceof Response ? candidate : new Response(body, candidate); Type guard
const isServableBody = (b: unknown): b is BodyInit => b === null || typeof b === 'string' || b instanceof Uint8Array || b instanceof Blob || b instanceof ReadableStream;
Prevention
- Only return Response objects created by the global Response constructor
- Never let bundles or packages replace globalThis.Response in a Deno server build
- Re-wrap Responses crossing package boundaries with new Response(foreign.body, foreign)
When it happens
Trigger: Returning a Response created by another package's Response class (undici, node-fetch, a test double), returning an object that only duck-types Response after prototype checks were bypassed, or a bundler/polyfill replacing globalThis.Response before Deno.serve inspects the returned value.
Common situations: SSR/framework code bundled with a fetch polyfill for Node compatibility, unit-test Response mocks accidentally used in a live server, monorepos where a shared package exports its own Response implementation.
Related errors
- Return value from onError handler must be a Response…
- Return value from serve handler must be a Response…
- First argument to 'respondWith' must be a Response…
- The body of the Response returned from the serve handler…
- Body is unusable
AI-assisted analysis of denoland/deno@abd22074e4 (2026-08-20).
Data as JSON: /api/errors/958fd14b95b7b535.
Report an issue: GitHub.
Appendix: source
Thrown at ext/http/00_serve.ts:670
if (typeof body === "string") {
innerRequest?.close();
if (headers?.length > 0) {
op_http_set_response_body_text_with_headers(
req,
body,
status,
headers,
);
} else {
op_http_set_response_body_text(req, body, status);
}
return;
}
// At this point in the response it needs to be a stream
if (!ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, stream)) {
innerRequest?.close();
throw new TypeError("Invalid response");
}
setResponseHeaders(req, headers);
const resourceBacking = getReadableStreamResourceBacking(stream);
let rid, autoClose;
if (resourceBacking) {
rid = resourceBacking.rid;
autoClose = resourceBacking.autoClose;
} else {
// The response headers/status have already been committed by the time the
// body stream starts producing chunks, so an error thrown while draining
// the stream (e.g. inside a `TransformStream` transformer) can no longer
// change the response. Report it through the server's error handler so it
// is not silently swallowed and a stack trace implicating the faulty
// callback is surfaced. See https://github.com/denoland/deno/issues/19867.
rid = resourceForReadableStream(stream, undefined, onError);
autoClose = true;
}
PromisePrototypeThen(View on GitHub (pinned to abd22074e4)