{"record":{"id":"e6b18143d9fb8144","repo":"denoland/deno","slug":"return-value-from-serve-handler-must-be-a-response-e6b181","errorCode":null,"errorMessage":"Return value from serve handler must be a Response constructed via the Response constructor in this realm","messagePattern":"Return value from serve 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":735,"sourceCode":"          request,\n          new ServeHandlerInfo(innerRequest),\n        );\n      }\n\n      // Throwing Error if the handler return value is not a Response class\n      if (!ObjectPrototypeIsPrototypeOf(ResponsePrototype, response)) {\n        throw new TypeError(\n          \"Return value from serve handler must be a response or a promise resolving to a response\",\n        );\n      }\n\n      // The Response prototype check above passes for Response-like objects\n      // (e.g. a subclass that skipped super(), or a Response from a different\n      // realm/polyfill). Those don't carry the internal slot we read from\n      // below, so reject them with a clear error instead of crashing later.\n      inner = getInnerResponse(response);\n      if (inner === undefined) {\n        throw new TypeError(\n          \"Return value from serve handler must be a Response constructed via the Response constructor in this realm\",\n        );\n      }\n\n      if (inner.type === \"error\") {\n        throw new TypeError(\n          \"Return value from serve handler must not be an error response (like Response.error())\",\n        );\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);","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/http/00_serve.ts#L717-L753","documentation":"The prototype check in serve passes for Response-like objects that lack the internal slot only real Responses carry: instances from another realm or polyfill, or a subclass whose constructor skipped super(). getInnerResponse returns undefined for such objects and serve rejects them with this clear error instead of crashing later while reading the internal slot.","triggerScenarios":"Returning a Response obtained from npm packages that bundle their own implementation (e.g. undici), a Response created inside a Worker/vm context, an object that merely subclasses Response without calling super(), or an object forged with Object.create(Response.prototype).","commonSituations":"Using npm HTTP clients or SDKs in Deno and forwarding their Response directly; SSR/framework code that routes through polyfills; Response subclasses written as `class R extends Response { constructor() { return {} as any; } }`.","solutions":["Re-create the response at the boundary with the realm's constructor: return new Response(foreign.body, { status: foreign.status, headers: foreign.headers })","If the foreign body is not a usable stream, buffer it first: new Response(await foreign.text(), ...)","In Response subclasses, always call super(...) so the internal slot is installed","Pass serialized data across realm boundaries instead of Response objects"],"exampleFix":"// before\nimport { fetch as undiciFetch } from \"npm:undici\";\nDeno.serve(async () => {\n  const r = await undiciFetch(\"https://example.com\");\n  return r; // undici Response: no Deno internal slot\n});\n\n// after\nimport { fetch as undiciFetch } from \"npm:undici\";\nDeno.serve(async () => {\n  const r = await undiciFetch(\"https://example.com\");\n  return new Response(r.body, { status: r.status, headers: r.headers });\n});","handlingStrategy":"type-guard","validationCode":"// Re-wrap anything that might be cross-realm before returning\nfunction toRealmResponse(v) {\n  if (v instanceof Response && Object.getPrototypeOf(v) === Response.prototype) {\n    return v;\n  }\n  if (v instanceof Response) {\n    return new Response(v.body, { status: v.status, headers: v.headers });\n  }\n  return new Response(String(v));\n}","typeGuard":"// Heuristic: accepts direct instances of THIS realm's Response;\n// valid subclasses should call super() and be re-wrapped at the boundary anyway\nfunction isRealmResponse(v) {\n  return v instanceof Response && v.constructor === Response;\n}","tryCatchPattern":"Deno.serve({\n  onError: (err) => new Response(\"Internal Server Error\", { status: 500 }),\n  handler: async (req) => {\n    try {\n      return await route(req);\n    } catch (err) {\n      if (err instanceof TypeError && err.message.includes(\"in this realm\")) {\n        return new Response(\"Cross-realm response rejected\", { status: 500 });\n      }\n      throw err;\n    }\n  },\n});","preventionTips":["Never forward Response objects from npm packages (undici) or other Workers; re-create them with the built-in Response","Always call super(...) in Response subclasses","Pass plain data across realm boundaries and build the Response where you serve it"],"tags":["http","serve","realm","interop","npm","response"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}