vitejs/vite · error · TypeError
FetchableDevEnvironment `context.handleRequest` must return
Error message
FetchableDevEnvironment `context.handleRequest` must return a `Response` object.
What it means
After dispatchFetch calls the user-supplied handleRequest at fetchableEnvironments.ts:56, it asserts the returned value is an instance of global Response. A handler that returns a string, a plain object, undefined, or a Response from a different constructor trips this guard, signalling the contract was broken.
Source
Thrown at packages/vite/src/node/server/environments/fetchableEnvironments.ts:56
constructor(
name: string,
config: ResolvedConfig,
context: FetchableDevEnvironmentContext,
) {
super(name, config, context)
this._handleRequest = context.handleRequest
}
public async dispatchFetch(request: Request): Promise<Response> {
if (!(request instanceof Request)) {
throw new TypeError(
'FetchableDevEnvironment `dispatchFetch` must receive a `Request` object.',
)
}
const response = await this._handleRequest(request)
if (!(response instanceof Response)) {
throw new TypeError(
'FetchableDevEnvironment `context.handleRequest` must return a `Response` object.',
)
}
return response
}
}
export type { FetchableDevEnvironment }
View on GitHub (pinned to 89620f09af)
Solutions
- Ensure handleRequest always returns new Response(...) (or a Response from the same global constructor).
- Wrap non-Response return values: return new Response(body, { status, headers }).
- If using a Response polyfill, reconcile it with globalThis.Response so instanceof passes.
Example fix
// before
handleRequest: async (req) => { return JSON.stringify(data) }
// after
handleRequest: async (req) =>
new Response(JSON.stringify(data), {
headers: { 'content-type': 'application/json' },
}) Defensive patterns
Strategy: type-guard
Validate before calling
function assertResponse(value: unknown) {
if (!(value instanceof Response)) {
throw new TypeError('handleRequest must return a global Response instance')
}
} Type guard
function isResponse(value: unknown): value is Response {
return typeof Response !== 'undefined' && value instanceof Response
} Prevention
- Always return new Response(...) from handleRequest.
- Annotate handleRequest's return type as Promise<Response> | Response so the compiler enforces it.
- Reconcile any Response polyfill with globalThis.Response to satisfy instanceof.
When it happens
Trigger: handleRequest returns JSON as a string instead of new Response(json); returns void; returns a Response-like object built by a different Response constructor (polyfill vs global); throws and the catch path returns a non-Response.
Common situations: SSR adapters that hand-roll response objects; frameworks migrating from express-style (res.send) to Fetch-style without wrapping; multiple Response constructors in the realm; forgotten return in the handler.
Related errors
- FetchableDevEnvironment `dispatchFetch` must receive a `Requ
- FetchableDevEnvironment requires a `handleRequest` method du
- Invalid environment name "${name}". Environment names must o
- Required environments configuration were stripped out in the
- FetchableDevEnvironment requires a global `Request` and `Res
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/28f084c3ca936d3b.json.
Report an issue: GitHub.