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

  1. Ensure handleRequest always returns new Response(...) (or a Response from the same global constructor).
  2. Wrap non-Response return values: return new Response(body, { status, headers }).
  3. 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

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


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/28f084c3ca936d3b.json. Report an issue: GitHub.