{"record":{"id":"7cc789d83f2b6729","repo":"denoland/deno","slug":"cannot-serve-http-requests-either-a-handler-or","errorCode":null,"errorMessage":"Cannot serve HTTP requests: either a `handler` or `options` must be specified","messagePattern":"Cannot serve HTTP requests: either a `handler` or `options` must be specified","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/00_serve.ts","lineNumber":1150,"sourceCode":"\n// Flag to track if DENO_SERVE_ADDRESS override has been consumed\nlet serveAddressOverrideConsumed = false;\n\nfunction serve(arg1, arg2) {\n  let options: RawServeOptions | undefined;\n  let handler: RawHandler | undefined;\n\n  if (typeof arg1 === \"function\") {\n    handler = arg1;\n  } else if (typeof arg2 === \"function\") {\n    handler = arg2;\n    options = arg1;\n  } else {\n    options = arg1;\n  }\n  if (handler === undefined) {\n    if (options === undefined) {\n      throw new TypeError(\n        \"Cannot serve HTTP requests: either a `handler` or `options` must be specified\",\n      );\n    }\n    handler = options.handler;\n  }\n  if (typeof handler !== \"function\") {\n    throw new TypeError(\n      `Cannot serve HTTP requests: handler must be a function, received ${typeof handler}`,\n    );\n  }\n  if (options === undefined) {\n    options = { __proto__: null };\n  }\n\n  if (serveAddressOverrideConsumed) {\n    return serveInner(options, handler);\n  }\n","sourceCodeStart":1132,"sourceCodeEnd":1168,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/http/00_serve.ts#L1132-L1168","documentation":"Deno.serve supports three call shapes: serve(handler), serve(options, handler), and serve(options-with-handler). The argument parser assigns handler only from a function argument or options.handler; when neither is present it throws this TypeError at startup so the misconfiguration fails fast instead of binding a useless listener.","triggerScenarios":"Calling Deno.serve() with no arguments; passing only network options such as Deno.serve({ port: 8000 }) and forgetting handler; passing the handler as the second argument to a plain options object that already lacks it.","commonSituations":"Migrating from std/http serve or Express, where the wiring differs; splitting config into a shared object and forgetting to add the handler key when copying examples.","solutions":["Pass the handler: Deno.serve(handler) or Deno.serve({ port: 8000, handler })","If options come from a config file, merge them with a local handler before calling serve","Check `typeof handler === 'function'` before calling serve in dynamic setups"],"exampleFix":"// before\nDeno.serve({ port: 8000 }); // no handler\n\n// after\nDeno.serve({ port: 8000, handler: (req) => new Response(\"ok\") });","handlingStrategy":"validation","validationCode":"// Validate serve arguments before calling it\nfunction assertServeArgs(arg1, arg2) {\n  const fn = typeof arg1 === \"function\" ? arg1 : (typeof arg2 === \"function\" ? arg2 : arg1?.handler);\n  if (typeof fn !== \"function\") {\n    throw new TypeError(\"Deno.serve requires a handler function\");\n  }\n}","typeGuard":"function hasServeHandler(arg1, arg2) {\n  return typeof arg1 === \"function\" || typeof arg2 === \"function\" ||\n    (typeof arg1?.handler === \"function\");\n}","tryCatchPattern":null,"preventionTips":["Default the handler when building options from config: serve({ ...cfg, handler: cfg.handler ?? fallback })","Run a smoke start of the server in CI so missing-handler configs fail there","Prefer the explicit serve({ port, handler }) shape in examples"],"tags":["http","serve","api-misuse","configuration"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}