{"record":{"id":"43b40eec402e4d12","repo":"denoland/deno","slug":"first-argument-to-respondwith-must-be-a-response","errorCode":null,"errorMessage":"First argument to 'respondWith' must be a Response or a promise resolving to a Response","messagePattern":"First argument to 'respondWith' must be a Response or a promise resolving to a Response","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/01_http.js","lineNumber":201,"sourceCode":"        const reqEvt = await httpConn.nextRequest();\n        // Change with caution, current form avoids a v8 deopt\n        return { value: reqEvt ?? undefined, done: reqEvt === null };\n      },\n    };\n  }\n}\n\nfunction createRespondWith(\n  httpConn,\n  request,\n  readStreamRid,\n  writeStreamRid,\n) {\n  return async function respondWith(resp) {\n    try {\n      resp = await resp;\n      if (!(ObjectPrototypeIsPrototypeOf(ResponsePrototype, resp))) {\n        throw new TypeError(\n          \"First argument to 'respondWith' 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      // that don't carry the internal slot (e.g. `Object.create(Response.prototype)`\n      // or a polyfilled/foreign-realm Response). Reject those here instead of\n      // crashing later on `innerResp.body`. Mirrors the Deno.serve guard\n      // added in #34416.\n      const innerResp = toInnerResponse(resp);\n      if (innerResp === undefined) {\n        throw new TypeError(\n          \"First argument to 'respondWith' must be a Response constructed via the Response constructor in this realm\",\n        );\n      }\n\n      // If response body length is known, it will be sent synchronously in a\n      // single op, in other case a \"response body\" resource will be created and","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/http/01_http.js#L183-L219","documentation":"Thrown inside the async respondWith closure created per-request by Deno.serveHttp(httpConn). It awaits the value the handler passed to httpConn.respondWith() and then requires it to have Response.prototype in its prototype chain. Anything that does not resolve to a real Response instance (plain object, string, number, undefined, a Response-like duck-typed object) triggers this TypeError.","triggerScenarios":"Calling httpConn.respondWith(new Request(...)) instead of a Response; returning/resolving to a plain object { status: 200, body: 'x' }; passing a string promise; passing undefined because an if/else branch forgot a return; passing a fetch-style WHATWG Response polyfill.","commonSituations":"Hand-rolled Deno.serveHttp loops migrated from service-worker style code; async handlers where one branch returns nothing; JSON helpers that return parsed bodies rather than Response objects; third-party Response polyfills leaking into the handler.","solutions":["Always resolve to a real Response: httpConn.respondWith(new Response(body, { status, headers })).","Audit every code path in the handler passed to respondWith so each returns a Response (add a fallback `return new Response('error', { status: 500 })`).","If you have a plain object, construct a Response from it instead of passing it directly.","Use Deno.serve(handler) instead of the low-level serveHttp loop unless you need raw connection control."],"exampleFix":"// before\nhttpConn.respondWith({ status: 200, body: \"hello\" });\n\n// after\nhttpConn.respondWith(new Response(\"hello\", { status: 200 }));","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"async function isResponse(v: unknown): Promise<boolean> { return Object.prototype.isPrototypeOf.call(Response.prototype, await v); }","tryCatchPattern":"try { await httpConn.respondWith(handlerResult); } catch (e) { if (e instanceof TypeError && /respondWith/.test(e.message)) { await httpConn.respondWith(new Response(\"bad handler\", { status: 500 })); return; } throw e; }","preventionTips":["Type handler return values as Response | Promise<Response> so the compiler enforces it.","Add an exhaustiveness fallback `return new Response('unreachable', { status: 500 })` to async branches.","Prefer Deno.serve(handler) over manual serveHttp loops unless you need raw connections."],"tags":["http","servehttp","response","web-apis"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}