denoland/deno · error · TypeError

Cannot serve HTTP requests: either a `handler` or `options`…

Error message

Cannot serve HTTP requests: either a `handler` or `options` must be specified

What it means

Deno.serve's argument parser accepts `serve(handler)`, `serve(options, handler)`, or `serve(optionsWithHandler)`; if none of the arguments is a function, `options` must exist and carry a `handler`. This TypeError fires when serve is called with no usable arguments at all — typically `Deno.serve()` or `Deno.serve(undefined)`. It is a startup-time configuration error, thrown synchronously before any listener is created.

Solutions

  1. Pass a handler function: `Deno.serve(handler)` or `Deno.serve({ port: 8000, handler })`
  2. If building options dynamically, fall back to a concrete options object: `Deno.serve(opts ?? { port: 8000, handler })`
  3. Check for undefined before calling when handlers come from dynamic imports

Example fix

// before
Deno.serve(); // no handler, no options

// after
Deno.serve({ port: 8000, handler: (req) => new Response('ok') });
Defensive patterns

Strategy: validation

Validate before calling

// Verify arguments before calling serve:
const handler: Deno.ServeHandler | undefined = resolveHandler();
if (typeof handler !== 'function') {
  throw new Error('Deno.serve: no handler resolved — check dynamic imports');
}
Deno.serve({ port: 8000 }, handler);

Type guard

const isServeHandler = (v: unknown): v is Deno.ServeHandler =>
  typeof v === 'function';

Prevention

When it happens

Trigger: Calling `Deno.serve()` with zero arguments while wiring code up, passing an undefined variable as the only argument (`Deno.serve(missingHandler)` where the import failed silently), or passing a non-function first argument and a non-function second argument so options stays undefined.

Common situations: Scaffolding/boilerplate run before the handler is written, circular imports yielding undefined handlers, dynamic construction of the serve arguments from config that produced nothing.

Related errors


AI-assisted analysis of denoland/deno@abd22074e4 (2026-08-20). Data as JSON: /api/errors/7cc789d83f2b6729. Report an issue: GitHub.

Appendix: source

Thrown at ext/http/00_serve.ts:1173

// Flag to track if DENO_SERVE_ADDRESS override has been consumed
let serveAddressOverrideConsumed = false;

function serve(arg1, arg2) {
  let options: RawServeOptions | undefined;
  let handler: RawHandler | undefined;

  if (typeof arg1 === "function") {
    handler = arg1;
  } else if (typeof arg2 === "function") {
    handler = arg2;
    options = arg1;
  } else {
    options = arg1;
  }
  if (handler === undefined) {
    if (options === undefined) {
      throw new TypeError(
        "Cannot serve HTTP requests: either a `handler` or `options` must be specified",
      );
    }
    handler = options.handler;
  }
  if (typeof handler !== "function") {
    throw new TypeError(
      `Cannot serve HTTP requests: handler must be a function, received ${typeof handler}`,
    );
  }
  if (options === undefined) {
    options = { __proto__: null };
  }

  if (serveAddressOverrideConsumed) {
    return serveInner(options, handler);
  }

View on GitHub (pinned to abd22074e4)