denoland/deno · error · TypeError
Return value from onError handler must be a Response…
Error message
Return value from onError handler must be a Response constructed via the Response constructor in this realm
What it means
The onError path performs the same two-step validation as the main handler: first the prototype check, then toInnerResponse()/getInnerResponse() for the internal Deno slot. This TypeError means the Response returned by onError passed `instanceof Response` but carries no internal slot — it came from a subclass that skipped super(), or from another realm/polyfill (undici, node-fetch, a mock). Deno then logs 'Exception in onError while handling exception' and sends the built-in 500.
Solutions
- Build onError's return value with the global Response constructor
- Call `super(init)` in any Response subclass used for error replies
- Re-wrap foreign objects: `return new Response(foreign.body, foreign)`
Example fix
// before
import { Response as NodeFetchResponse } from 'node-fetch';
onError: (e) => new NodeFetchResponse(e.message, { status: 500 }),
// after
onError: (e) => new Response(e.message, { status: 500 }), // global Response Defensive patterns
Strategy: validation
Validate before calling
// Normalize anything onError might return into a native Response:
onError: (e) => {
const out = buildErrorPage(e); // possibly foreign
return out instanceof Response ? new Response(out.body, out) : new Response('Internal Server Error', { status: 500 });
} Try / catch
// A second failure falls back to the built-in 500 automatically; log it:
// 'Exception in onError while handling exception' appears in server logs — check there first
Deno.serve({ handler, onError }); Prevention
- Build error Responses with the global Response constructor
- Do not import Response from polyfills anywhere in the error path
- Call super() in Response subclasses used for error replies
When it happens
Trigger: onError returning a Response imported from undici/node-fetch, a Response subclass in the error path whose constructor never calls super(), or `Object.create(Response.prototype)` stubs used to fake error responses.
Common situations: Centralized error handlers in frameworks that import their own fetch polyfill, custom error-Response wrapper classes, test harnesses injecting fake Responses into onError.
Related errors
- Invalid response
- Return value from serve handler must be a Response…
- First argument to 'respondWith' must be a Response…
- Return value from onError handler must be a response or a…
- Both 'cert' and 'key' must be provided to enable HTTPS
AI-assisted analysis of denoland/deno@abd22074e4 (2026-08-20).
Data as JSON: /api/errors/e73e78f6d6c228f9.
Report an issue: GitHub.
Appendix: source
Thrown at ext/http/00_serve.ts:780
);
}
if (responseBodyUsed(response)) {
throw new TypeError(
"The body of the Response returned from the serve handler has already been consumed",
);
}
} catch (error) {
try {
response = await onError(error);
if (!ObjectPrototypeIsPrototypeOf(ResponsePrototype, response)) {
throw new TypeError(
"Return value from onError handler must be a response or a promise resolving to a response",
);
}
inner = toInnerResponse(response);
if (inner === undefined) {
throw new TypeError(
"Return value from onError handler must be a Response constructed via the Response constructor in this realm",
);
}
} catch (error) {
if (otelState.METRICS_ENABLED) {
op_http_metric_handle_otel_error(req);
}
internals.log(
"error",
"Exception in onError while handling exception",
error,
);
response = internalServerError();
inner = toInnerResponse(response);
}
}
if (span) {View on GitHub (pinned to abd22074e4)