{"record":{"id":"b41ecb8ad95ce0ec","repo":"denoland/deno","slug":"return-value-from-serve-handler-must-be-a-response","errorCode":null,"errorMessage":"Return value from serve handler must be a response or a promise resolving to a response","messagePattern":"Return value from serve handler must be a response or a promise resolving to a response","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/00_serve.ts","lineNumber":724,"sourceCode":"        response = await callback();\n      } else {\n        innerRequest = new InnerRequest(req, context);\n        const request = fromInnerRequest(innerRequest, \"immutable\");\n        innerRequest.request = request;\n\n        if (span) {\n          updateSpanFromRequest(span, request);\n        }\n\n        response = await callback(\n          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())\",","sourceCodeStart":706,"sourceCodeEnd":742,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/http/00_serve.ts#L706-L742","documentation":"Deno.serve requires the handler (or the promise it returns) to resolve to an instance of the built-in Response. Before sending, serve validates the value's prototype chain; anything else (string, plain object, undefined) throws this TypeError so the failure surfaces in the handler's context instead of crashing the native layer. The throw is routed to onError, which by default produces a 500 response.","triggerScenarios":"Returning 'ok', a parsed JSON object (await res.json()), or a URL from the handler; a code path that falls off the end without a return statement; a middleware branch that forgets 'return next(request)'.","commonSituations":"Porting Express-style handlers that used res.send(...); early-return guard clauses with a missing return; returning the result of a fetch().json() call instead of the fetch Response itself.","solutions":["Wrap non-Response values: return new Response('ok') or return Response.json(data)","Audit every branch of the handler, including catch blocks, so each path returns a Response","In middleware chains, always return the downstream handler's result","Type the handler as (req: Request) => Response | Promise<Response> so mismatches surface at compile time"],"exampleFix":"// before\nDeno.serve((req) => {\n  if (req.url.endsWith(\"/health\")) return \"ok\"; // plain string\n  return appHandler(req);\n});\n\n// after\nDeno.serve((req) => {\n  if (req.url.endsWith(\"/health\")) return new Response(\"ok\");\n  return appHandler(req);\n});","handlingStrategy":"type-guard","validationCode":"// Validate before returning from any handler path\nif (!(response instanceof Response)) {\n  response = new Response(String(response));\n}\nreturn response;","typeGuard":"function isResponse(v) {\n  return v instanceof Response;\n}","tryCatchPattern":"Deno.serve({\n  onError: (err) =>\n    err instanceof TypeError &&\n      err.message.includes(\"must be a response or a promise\")\n      ? new Response(\"Handler must return a Response\", { status: 500 })\n      : new Response(\"Internal Server Error\", { status: 500 }),\n  handler,\n});","preventionTips":["Type handlers as (req: Request) => Response | Promise<Response>","Return Response.json(data) instead of raw objects","Check every guard clause and catch block for a missing Response return"],"tags":["http","serve","handler","response","typeerror"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}