{"record":{"id":"ad09447b4c0b5139","repo":"nodejs/node","slug":"invalid-interceptor","errorCode":null,"errorMessage":"invalid interceptor","messagePattern":"invalid interceptor","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/dispatcher/dispatcher.js","lineNumber":34,"sourceCode":"\n  compose (...args) {\n    // So we handle [interceptor1, interceptor2] or interceptor1, interceptor2, ...\n    const interceptors = Array.isArray(args[0]) ? args[0] : args\n    let dispatch = this.dispatch.bind(this)\n\n    for (const interceptor of interceptors) {\n      if (interceptor == null) {\n        continue\n      }\n\n      if (typeof interceptor !== 'function') {\n        throw new TypeError(`invalid interceptor, expected function received ${typeof interceptor}`)\n      }\n\n      dispatch = interceptor(dispatch)\n\n      if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) {\n        throw new TypeError('invalid interceptor')\n      }\n    }\n\n    return new Proxy(this, {\n      get: (target, key) => key === 'dispatch' ? dispatch : target[key]\n    })\n  }\n}\n\nmodule.exports = Dispatcher\n","sourceCodeStart":16,"sourceCodeEnd":45,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/dispatcher/dispatcher.js#L16-L45","documentation":"TypeError thrown by Dispatcher.compose() when an interceptor returns a value that is not a function of arity 2 (opts, handler). After calling interceptor(dispatch), undici requires the result to be a non-null function whose .length === 2, since the dispatch contract is (opts, handler) => boolean. A null return, a non-function, or a function with the wrong arity all trigger this.","triggerScenarios":"Writing an interceptor that returns undefined, returns a 0/1/3-arg function, returns an object, or forgets to return. Fires at dispatcher.js:33-34.","commonSituations":"Interceptor wraps dispatch in a closure with extra bound args (changing .length); interceptor returns the raw handler instead of a dispatch function; missing `return` in a single-expression arrow that implicitly returns undefined; curry-style interceptor that captures opts early.","solutions":["Ensure the interceptor returns (opts, handler) => dispatch(opts, handler) shaped exactly with two declared parameters.","If you pre-bind arguments, wrap so the returned function declares (opts, handler) explicitly.","Always return the new dispatch function; do not rely on implicit returns from blocks."],"exampleFix":"// before\nclient.compose((dispatch) => {\n  return (opts) => dispatch(opts) // wrong arity, no handler\n})\n// after\nclient.compose((dispatch) => {\n  return (opts, handler) => dispatch(opts, handler)\n})","handlingStrategy":"validation","validationCode":"function checkInterceptor(fn) {\n  const out = fn(cur => (opts, handler) => cur(opts, handler));\n  if (out == null || typeof out !== 'function' || out.length !== 2) {\n    throw new TypeError('interceptor must return a 2-arg (opts, handler) function');\n  }\n  return out;\n}","typeGuard":"typeof next === 'function' && next.length === 2","tryCatchPattern":null,"preventionTips":["Always return a function declared as (opts, handler) => ... from interceptors.","Do not bind extra arguments that change the function arity.","Add a unit test asserting the wrapped dispatch has length === 2."],"tags":["undici","dispatcher","interceptor","compose","typeerror","arity"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}