sindresorhus/got · error · Error

Missing hook event: ${knownHookEvent}

Error message

Missing hook event: ${knownHookEvent}

What it means

Thrown by the `hooks` setter (in the non-merging code path, i.e. when setting hooks directly rather than via `got.extend`) when a hook event key is present in the object but its value is falsy/empty. When you assign `hooks` outright each event you list must be backed by an actual array of functions; an undefined/null entry is treated as a missing implementation.

Source

Thrown at source/core/options.ts:2463

			const typedKnownHookEvent = knownHookEvent as keyof Hooks;
			const hooks = value[typedKnownHookEvent];

			assertAny(`hooks.${knownHookEvent}`, [is.array, is.undefined], hooks);

			if (hooks) {
				for (const hook of hooks) {
					assert.function(hook);
				}
			}

			if (this.#merging) {
				if (hooks) {
					// @ts-expect-error FIXME
					this.#internals.hooks[typedKnownHookEvent].push(...hooks);
				}
			} else {
				if (!hooks) {
					throw new Error(`Missing hook event: ${knownHookEvent}`);
				}

				// @ts-expect-error FIXME
				this.#internals.hooks[knownHookEvent] = [...hooks];
			}
		}
	}

	/**
	Whether redirect responses should be followed automatically.

 	Optionally, pass a function to dynamically decide based on the response object.

	Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`.
	This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`.
	On cross-origin redirects, Got strips `host`, `cookie`, `cookie2`, `authorization`, and `proxy-authorization`. When a redirect rewrites the request to `GET`, Got also strips request body headers. Use `hooks.beforeRedirect` for app-specific sensitive headers.

	@default true

View on GitHub (pinned to e3924aa1e5)

Solutions

  1. Omit the key entirely instead of setting it to undefined/null: only include events that have a real array.
  2. Build the hooks object conditionally so falsy entries are not inserted.
  3. Default each event to an empty array `[]` if you must list the key.

Example fix

// before
const hooks = {beforeRequest: useAuth ? authHook : undefined};
await got(url, {hooks});
// after
const hooks = {};
if (useAuth) hooks.beforeRequest = [authHook];
await got(url, {hooks});
Defensive patterns

Strategy: validation

Validate before calling

function stripFalsyHooks(hooks) {
  const out = {};
  for (const [ev, fns] of Object.entries(hooks ?? {})) {
    if (Array.isArray(fns) && fns.length > 0) out[ev] = fns;
  }
  return out;
}

Prevention

When it happens

Trigger: Calling `got(url, {hooks: {beforeRequest: undefined}})` or `{hooks: {beforeRequest: null}}` (or an empty value) directly on a request. Note: this does not fire for `got.extend({hooks: {...}})` merges, where undefined entries are tolerated.

Common situations: Conditionally building a hooks object where some keys end up undefined (e.g. `{beforeRequest: cond ? fn : undefined}`); spreading partial hook configs.

Related errors


AI-assisted analysis of sindresorhus/got@e3924aa1e5 (2026-08-03). Data as JSON: /data/errors/1c081aeaaa443d03.json. Report an issue: GitHub.