{"record":{"id":"28f084c3ca936d3b","repo":"vitejs/vite","slug":"fetchabledevenvironment-context-handlerequest-mu","errorCode":null,"errorMessage":"FetchableDevEnvironment `context.handleRequest` must return a `Response` object.","messagePattern":"FetchableDevEnvironment `context\\.handleRequest` must return a `Response` object\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/server/environments/fetchableEnvironments.ts","lineNumber":56,"sourceCode":"\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    context: FetchableDevEnvironmentContext,\n  ) {\n    super(name, config, context)\n    this._handleRequest = context.handleRequest\n  }\n\n  public async dispatchFetch(request: Request): Promise<Response> {\n    if (!(request instanceof Request)) {\n      throw new TypeError(\n        'FetchableDevEnvironment `dispatchFetch` must receive a `Request` object.',\n      )\n    }\n    const response = await this._handleRequest(request)\n    if (!(response instanceof Response)) {\n      throw new TypeError(\n        'FetchableDevEnvironment `context.handleRequest` must return a `Response` object.',\n      )\n    }\n    return response\n  }\n}\n\nexport type { FetchableDevEnvironment }\n","sourceCodeStart":38,"sourceCodeEnd":65,"githubUrl":"https://github.com/vitejs/vite/blob/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/node/server/environments/fetchableEnvironments.ts#L38-L65","documentation":"Thrown by FetchableDevEnvironment.dispatchFetch() after invoking the user-supplied handleRequest, when its returned value is not an instance of the global Response class. The environment enforces the Fetch API contract on the way out so callers can safely treat dispatchFetch as returning a real Response.","triggerScenarios":"handleRequest returns a plain object ({ status, body }), a string, JSON via res.json(), or a fetch() result from a different Realm/fetch implementation so `response instanceof Response` is false. The check is at fetchableEnvironments.ts:55.","commonSituations":"A handler that returns a framework-specific response object (e.g. a Next/Hono Response that isn't the global Response), or returns `await res.json()` instead of the Response itself. A handler that forgets to return. Multiple fetch polyfills (undici vs node:fetch vs window.fetch) creating non-identical Response classes.","solutions":["Make handleRequest return the Response object directly (return fetch(...)), not a parsed body.","If you build a response manually, return new Response(body, { status, headers }).","Ensure the Response class your handler uses is the same global Response the environment checks against (avoid mixing fetch polyfills)."],"exampleFix":"// before\nasync handleRequest(req) { return JSON.stringify(await fetchHandler(req)) }\n// after\nasync handleRequest(req) { return fetchHandler(req) /* returns a Response */ }","handlingStrategy":"type-guard","validationCode":"const res = await handleRequest(request)\nif (!(res instanceof Response)) {\n  throw new TypeError('handleRequest must return a Response')\n}","typeGuard":"function isResponse(v: unknown): v is Response {\n  return typeof Response !== 'undefined' && v instanceof Response\n}","tryCatchPattern":null,"preventionTips":["Make handleRequest return the Response from fetch()/new Response() directly.","Avoid mixing fetch implementations (undici/node/window) in one process."],"tags":["fetchable-environment","fetch-api","type-mismatch"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}