honojs/hono · error · TypeError
env has to include the 2nd argument of fetch.
Error message
env has to include the 2nd argument of fetch.
What it means
Hono's Bun adapter getConnInfo() needs access to the Bun `Server` object that served the request. On Bun, that server instance is only available when Hono is mounted via `Bun.serve({ fetch: app.fetch, ... })` — Bun passes the server as the second argument of fetch(), and Hono stores it in `c.env`. If getConnInfo() is called outside that setup, `c.env.server` is undefined and this TypeError is thrown.
Source
Thrown at src/adapter/bun/conninfo.ts:20
import type { GetConnInfo } from '../../helper/conninfo'
import { getBunServer } from './server'
/**
* Get ConnInfo with Bun
* @param c Context
* @returns ConnInfo
*/
export const getConnInfo: GetConnInfo = (c: Context) => {
const server = getBunServer<{
requestIP?: (req: Request) => {
address: string
family: string
port: number
} | null
}>(c)
if (!server) {
throw new TypeError('env has to include the 2nd argument of fetch.')
}
if (typeof server.requestIP !== 'function') {
throw new TypeError('server.requestIP is not a function.')
}
// https://bun.sh/docs/runtime/http/server#server-requestip-request
// Returns null for closed requests or Unix domain sockets.
const info = server.requestIP(c.req.raw)
if (!info) {
return {
remote: {},
}
}
return {
remote: {
address: info.address,View on GitHub (pinned to e2740d5a1b)
Solutions
- Mount the app correctly for Bun: `const server = Bun.serve({ fetch: app.fetch, port: 3000 })` so Bun injects the server into c.env
- If you wrap fetch, forward all arguments: `Bun.serve({ fetch: (...args) => app.fetch(...args) })`
- Guard before calling: check `getConnInfo` is only used inside a real Bun.serve request, e.g. wrap in try/catch or feature-detect the runtime
- In tests, call getConnInfo only against a real Bun.serve instance, not app.request()
Example fix
// before
const app = new Hono()
app.get((c) => c.json({ ip: getConnInfo(c).remote.address }))
// started in a way that drops Bun's server arg
Bun.serve({ fetch: (req) => app.fetch(req) }) // throws
// after
Bun.serve({ fetch: app.fetch, port: 3000 }) // Bun passes (req, server) -> c.env.server Defensive patterns
Strategy: validation
Validate before calling
import { getConnInfo } from 'hono/bun'
function hasBunServer(c: Context): boolean {
return Boolean((c.env as any)?.server)
}
app.get('/ip', (c) => {
if (!hasBunServer(c)) return c.text('ip unavailable', 200)
return c.json(getConnInfo(c))
}) Type guard
const isBunServerEnv = (
env: unknown
): env is { server: { requestIP(req: Request): { address: string; family: string; port: number } } } =>
typeof (env as any)?.server?.requestIP === 'function' Try / catch
try { const info = getConnInfo(c) } catch (e) { if (e instanceof TypeError && e.message.startsWith('env has to include')) { /* fall back to x-forwarded-for */ } else throw e } Prevention
- Always mount Hono as Bun.serve({ fetch: app.fetch }) so Bun injects the server
- Forward all fetch args in wrappers: (...args) => app.fetch(...args)
- Feature-detect c.env.server before calling getConnInfo in code shared across runtimes
When it happens
Trigger: Calling `getConnInfo(c)` from `hono/bun` when the app was not registered as the `fetch` handler of `Bun.serve()` (e.g. using `app.fetch` standalone, running under Node.js/deno, or a custom fetch wrapper that drops Bun's second `server` argument), so `c.env.server` is falsy.
Common situations: Porting a Hono app from Node (via @hono/node-server) to Bun and forgetting to switch to `Bun.serve({ fetch: app.fetch })`; unit tests calling handlers with `app.request()` where no Bun server exists; wrapping app.fetch in a closure like `(req) => app.fetch(req)` which discards the `server` parameter.
Related errors
- server.requestIP is not a function.
- env has to include the 2nd argument of fetch.
- Failed to upgrade WebSocket
- This context has no FetchEvent
- This context has no ExecutionContext
AI-assisted analysis of honojs/hono@e2740d5a1b (2026-08-28).
Data as JSON: /api/errors/c6bff888107efaba.
Report an issue: GitHub.