{"record":{"id":"e73e78f6d6c228f9","repo":"denoland/deno","slug":"return-value-from-onerror-handler-must-be-a-respon-e73e78","errorCode":null,"errorMessage":"Return value from onError handler must be a Response constructed via the Response constructor in this realm","messagePattern":"Return value from onError handler must be a Response constructed via the Response constructor in this realm","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/00_serve.ts","lineNumber":761,"sourceCode":"        );\n      }\n\n      if (responseBodyUsed(response)) {\n        throw new TypeError(\n          \"The body of the Response returned from the serve handler has already been consumed\",\n        );\n      }\n    } catch (error) {\n      try {\n        response = await onError(error);\n        if (!ObjectPrototypeIsPrototypeOf(ResponsePrototype, response)) {\n          throw new TypeError(\n            \"Return value from onError handler must be a response or a promise resolving to a response\",\n          );\n        }\n        inner = toInnerResponse(response);\n        if (inner === undefined) {\n          throw new TypeError(\n            \"Return value from onError handler must be a Response constructed via the Response constructor in this realm\",\n          );\n        }\n      } catch (error) {\n        if (otelState.METRICS_ENABLED) {\n          op_http_metric_handle_otel_error(req);\n        }\n        internals.log(\n          \"error\",\n          \"Exception in onError while handling exception\",\n          error,\n        );\n        response = internalServerError();\n        inner = toInnerResponse(response);\n      }\n    }\n\n    if (span) {","sourceCodeStart":743,"sourceCodeEnd":779,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/http/00_serve.ts#L743-L779","documentation":"The Response returned by onError goes through the same validation as a handler response: it must be a real Response carrying the internal slot of this realm. toInnerResponse returns undefined for cross-realm or polyfill instances (and prototype-forged objects), and serve rejects them with this TypeError. Because it is thrown inside the error path, only the internal 'Exception in onError while handling exception' log remains; the client gets a 500.","triggerScenarios":"onError returning a Response imported from an npm package (e.g. undici), a Response built inside a Worker, or a subclass that skipped super().","commonSituations":"Centralized error handlers that re-export or forward Response objects from third-party SDKs; polyfilled environments layered on top of Deno.","solutions":["Re-create the response inside onError with the built-in Response constructor","Buffer cross-realm bodies first: new Response(await foreign.text(), { status: 500, headers: foreign.headers })","Ensure any Response subclass used in onError calls super(...)"],"exampleFix":"// before\nimport { Response as NodeResponse } from \"npm:undici\";\nDeno.serve({\n  onError: (e) => new NodeResponse(e.message, { status: 500 }), // wrong realm\n  handler,\n});\n\n// after\nimport { Response as NodeResponse } from \"npm:undici\";\nDeno.serve({\n  onError: (e) => new Response(e.message, { status: 500 }), // built-in Response\n  handler,\n});","handlingStrategy":"type-guard","validationCode":"// Normalize onError output to this realm's Response\nconst onError = (err) => {\n  const r = buildErrorResponse(err); // may be cross-realm\n  return r instanceof Response && r.constructor === Response\n    ? r\n    : new Response(\"Internal Server Error\", { status: 500 });\n};","typeGuard":"function isRealmResponse(v) {\n  return v instanceof Response && v.constructor === Response;\n}","tryCatchPattern":"// A failing onError already degrades to a logged 500; keep it simple:\nconst onError = (err) => new Response(\"Internal Server Error\", { status: 500 });","preventionTips":["Construct error responses inline with the built-in Response constructor","Do not return undici/Worker Responses from onError","Unit-test the onError path, not just the happy path"],"tags":["http","serve","on-error","realm","interop"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}