{"record":{"id":"585209ee9d273484","repo":"denoland/deno","slug":"the-name-argument-must-be-of-type-function-r","errorCode":null,"errorMessage":"The \"${name}\" argument must be of type function. Received ${typeof value}","messagePattern":"The \"(.+?)\" argument must be of type function\\. Received (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/v8.ts","lineNumber":681,"sourceCode":"// ---------------------------------------------------------------------------\n\ntype PromiseHookFn = (\n  promise: Promise<unknown>,\n  parent?: Promise<unknown>,\n) => void;\n\nfunction validatePlainFunction(value: unknown, name: string) {\n  // Reject non-functions as well as async functions and async generators -\n  // none of them can be used as promise hooks.\n  const ctorName = typeof value === \"function\"\n    ? (value as { constructor?: { name?: string } }).constructor?.name\n    : undefined;\n  if (\n    typeof value !== \"function\" ||\n    ctorName === \"AsyncFunction\" ||\n    ctorName === \"AsyncGeneratorFunction\"\n  ) {\n    throw new TypeError(\n      `The \"${name}\" argument must be of type function. Received ${typeof value}`,\n    );\n  }\n}\n\n// Track all registered hooks so we can rebuild the combined hooks\n// when individual hooks are added/removed.\nconst initHooks: PromiseHookFn[] = [];\nconst beforeHooks: PromiseHookFn[] = [];\nconst afterHooks: PromiseHookFn[] = [];\nconst resolveHooks: PromiseHookFn[] = [];\n\n// Re-entrancy guard: V8 promise hooks fire for ALL promise operations,\n// including any promises created/resolved inside the hooks themselves.\nlet inPromiseHook = false;\n\n// Register dispatchers once. core.setPromiseHooks is additive (no removal),\n// so we install permanent dispatchers that check the current hook arrays.","sourceCodeStart":663,"sourceCodeEnd":699,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/v8.ts#L663-L699","documentation":"v8.promiseHooks.setOnInit/setBefore/setAfter/setResolve (and the combined alias) require plain synchronous functions. validatePlainFunction rejects non-functions and additionally rejects async functions and async generators (constructor.name AsyncFunction / AsyncGeneratorFunction), because hooks fire for every promise operation — awaiting inside a hook would recurse infinitely. The failure is a TypeError naming the argument.","triggerScenarios":"v8.promiseHooks.onInit(async (p) => { ... }), passing undefined or a string, or wiring a hook variable that was never assigned a function value.","commonSituations":"Diagnostic/tracing hooks written with await inside; async_hooks-style tracers ported to promiseHooks without removing await; hooks supplied by plugins or configuration where the value arrives as something other than a function.","solutions":["Make the hook synchronous: record data (queue, counter) inside the hook and process it elsewhere.","Replace await with fire-and-forget .then(...) on an external promise if async work is unavoidable.","Check the value is a function before registering when hooks come from config or plugins."],"exampleFix":"// before\nv8.promiseHooks.setOnInit(async (promise) => { await log(promise); }); // TypeError\n\n// after\nv8.promiseHooks.setOnInit((promise) => { logQueue.push(promise); }); // sync only","handlingStrategy":"type-guard","validationCode":"function assertSyncHook(fn, name) {\n  if (!isPlainFunction(fn)) throw new TypeError(`${name} must be a sync function`);\n}","typeGuard":"const isPlainFunction = (v) =>\n  typeof v === \"function\" &&\n  v.constructor?.name !== \"AsyncFunction\" &&\n  v.constructor?.name !== \"AsyncGeneratorFunction\";","tryCatchPattern":null,"preventionTips":["Never await inside a promise hook; your own promise work re-enters the hook.","Queue observations in hooks and drain them outside (microtask/setImmediate loop).","Validate third-party hook plugins with the sync-function guard before registration."],"tags":["v8","promise-hooks","async","typeerror"],"backgroundTag":"callback-type-validation","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}