{"id":"0cec8a746f247355","repo":"sindresorhus/got","slug":"unexpected-hook-event-knownhookevent","errorCode":null,"errorMessage":"Unexpected hook event: ${knownHookEvent}","messagePattern":"Unexpected hook event: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"source/core/options.ts","lineNumber":2442,"sourceCode":"\n\t/**\n\tHooks allow modifications during the request lifecycle.\n\tHook functions may be async and are run serially.\n\t*/\n\tget hooks(): Hooks {\n\t\treturn this.#internals.hooks;\n\t}\n\n\tset hooks(value: Hooks) {\n\t\tassert.object(value);\n\n\t\tfor (const knownHookEvent of Object.keys(value)) {\n\t\t\tif (knownHookEvent === '__proto__') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!(knownHookEvent in this.#internals.hooks)) {\n\t\t\t\tthrow new Error(`Unexpected hook event: ${knownHookEvent}`);\n\t\t\t}\n\n\t\t\tconst typedKnownHookEvent = knownHookEvent as keyof Hooks;\n\t\t\tconst hooks = value[typedKnownHookEvent];\n\n\t\t\tassertAny(`hooks.${knownHookEvent}`, [is.array, is.undefined], hooks);\n\n\t\t\tif (hooks) {\n\t\t\t\tfor (const hook of hooks) {\n\t\t\t\t\tassert.function(hook);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.#merging) {\n\t\t\t\tif (hooks) {\n\t\t\t\t\t// @ts-expect-error FIXME\n\t\t\t\t\tthis.#internals.hooks[typedKnownHookEvent].push(...hooks);\n\t\t\t\t}","sourceCodeStart":2424,"sourceCodeEnd":2460,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/options.ts#L2424-L2460","documentation":"Thrown by the `hooks` setter when the hooks object has a key that is not a recognized lifecycle event. Valid events are `init`, `beforeRequest`, `beforeRedirect`, `beforeRetry`, `beforeError`, `afterResponse`. Unknown event names are rejected so a misspelled hook (which would simply never fire) is caught loudly.","triggerScenarios":"Calling `got(url, {hooks: {beforRequest: [fn]}})` (typo), `{hooks: {onResponse: [fn]}}` (wrong name), or any hooks object key outside the six documented events.","commonSituations":"Typos in event names; copying hook names from another HTTP library; using a hook that only exists in a different Got major version.","solutions":["Use only the documented events: `init`, `beforeRequest`, `beforeRedirect`, `beforeRetry`, `beforeError`, `afterResponse`.","Check the `${knownHookEvent}` in the message and fix the typo.","Move any non-lifecycle logic into a `beforeRequest` hook or the `context` option."],"exampleFix":"// before\ngot.extend({hooks: {beforRequest: [opts => { opts.headers.auth = token; }]}});\n// after\ngot.extend({hooks: {beforeRequest: [opts => { opts.headers.auth = token; }]}});","handlingStrategy":"type-guard","validationCode":"const validHookEvents = new Set(['init','beforeRequest','beforeRedirect','beforeRetry','beforeError','afterResponse']);\nfunction validateHooks(hooks) {\n  for (const ev of Object.keys(hooks ?? {})) {\n    if (!validHookEvents.has(ev)) throw new Error(`Unknown hook event: ${ev}`);\n  }\n}","typeGuard":"import type {Hooks} from 'got';\nfunction isHooks(v: unknown): v is Hooks {\n  if (typeof v !== 'object' || v === null) return false;\n  return Object.keys(v).every(k => ['init','beforeRequest','beforeRedirect','beforeRetry','beforeError','afterResponse','__proto__'].includes(k));\n}","tryCatchPattern":null,"preventionTips":["Use the `Hooks` type so typos are compile errors.","Keep a shared constant of allowed events and lint against it."],"tags":["options","hooks","validation","typo","config"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}