vitejs/vite · error · TypeError

FetchableDevEnvironment requires a `handleRequest` method du

Error message

FetchableDevEnvironment requires a `handleRequest` method during initialisation.

What it means

createFetchableDevEnvironment at fetchableEnvironments.ts:22 requires context.handleRequest to be present, because dispatchFetch delegates every request to it. Omitting it leaves the environment unable to serve anything, so the constructor throws a TypeError at init time.

Source

Thrown at packages/vite/src/node/server/environments/fetchableEnvironments.ts:22

import type { Environment } from '../../environment'

export interface FetchableDevEnvironmentContext extends DevEnvironmentContext {
  handleRequest(request: Request): Promise<Response> | Response
}

export function createFetchableDevEnvironment(
  name: string,
  config: ResolvedConfig,
  context: FetchableDevEnvironmentContext,
): FetchableDevEnvironment {
  if (typeof Request === 'undefined' || typeof Response === 'undefined') {
    throw new TypeError(
      'FetchableDevEnvironment requires a global `Request` and `Response` object.',
    )
  }

  if (!context.handleRequest) {
    throw new TypeError(
      'FetchableDevEnvironment requires a `handleRequest` method during initialisation.',
    )
  }

  return new FetchableDevEnvironment(name, config, context)
}

export function isFetchableDevEnvironment(
  environment: Environment,
): environment is FetchableDevEnvironment {
  return environment instanceof FetchableDevEnvironment
}

class FetchableDevEnvironment extends DevEnvironment {
  private _handleRequest: (request: Request) => Promise<Response> | Response

  constructor(
    name: string,

View on GitHub (pinned to 89620f09af)

Solutions

  1. Provide context.handleRequest as a function (request: Request) => Promise<Response> | Response when calling createFetchableDevEnvironment.
  2. Double-check the FetchableDevEnvironmentContext interface — handleRequest is required, not optional.
  3. If you have no request handler yet, use DevEnvironment directly instead of the Fetchable variant.

Example fix

// before
const env = createFetchableDevEnvironment('ssr', config, { transport })

// after
const env = createFetchableDevEnvironment('ssr', config, {
  transport,
  handleRequest: (req) => app.ssrFetch(req),
})
Defensive patterns

Strategy: type-guard

Validate before calling

function assertHandlerContext(ctx: { handleRequest?: unknown }) {
  if (typeof ctx.handleRequest !== 'function') {
    throw new Error('FetchableDevEnvironment requires context.handleRequest')
  }
}

Type guard

function hasHandleRequest(ctx: { handleRequest?: unknown }): ctx is { handleRequest: (r: Request) => Promise<Response> | Response } {
  return typeof ctx.handleRequest === 'function'
}

Prevention

When it happens

Trigger: Calling createFetchableDevEnvironment with a context object that lacks handleRequest; passing a context typed loosely (any) where the function was forgotten; refactoring that renamed handleRequest to onRequest or similar.

Common situations: SSR framework integration that forgot to wire the request handler; copy-paste from DevEnvironment examples (which do not need handleRequest) into a Fetchable setup; TypeScript bypassed with as any hiding the missing field.

Related errors


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