{"record":{"id":"205243b89f20967a","repo":"nodejs/node","slug":"expected-type-of-opts-to-be-an-object-got-opts","errorCode":null,"errorMessage":"expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}","messagePattern":"expected type of opts to be an Object, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/interceptor/cache.js","lineNumber":511,"sourceCode":"\n  sendCachedValue(handler, opts, result, age, null, false)\n}\n\n/**\n * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions} [opts]\n * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor}\n */\nmodule.exports = (opts = {}) => {\n  const {\n    store = new MemoryCacheStore(),\n    methods = ['GET'],\n    cacheByDefault = undefined,\n    type = 'shared',\n    origins = undefined\n  } = opts\n\n  if (typeof opts !== 'object' || opts === null) {\n    throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`)\n  }\n\n  assertCacheStore(store, 'opts.store')\n  assertCacheMethods(methods, 'opts.methods')\n  assertCacheOrigins(origins, 'opts.origins')\n\n  if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') {\n    throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`)\n  }\n\n  if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') {\n    throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`)\n  }\n\n  const globalOpts = {\n    store,\n    methods,\n    cacheByDefault,","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/interceptor/cache.js#L493-L529","documentation":"Thrown by the cache() interceptor factory when the opts argument is not an object. Because the factory signature is (opts = {}), a value must be an object (or undefined to use the default); passing null, a string, a number, an array, or a boolean is rejected. Note null is reported as 'null' rather than 'object'.","triggerScenarios":"Calling interceptors.cache(null), interceptors.cache(false), interceptors.cache('shared'), or interceptors.cache(somePrimitive) explicitly.","commonSituations":"Conditionally passing a config object and accidentally forwarding a falsy value (null/0/false) instead of undefined; spreading config that resolved to null; misreading the API as accepting a string mode.","solutions":["Pass an object or omit the argument entirely: interceptors.cache() uses defaults.","Normalize at the call site: const opts = config ?? undefined before composing.","Guard with typeof before forwarding dynamic config."],"exampleFix":"// before\nclient.compose(interceptors.cache(maybeConfig)) // maybeConfig can be null\n\n// after\nclient.compose(interceptors.cache(maybeConfig ?? undefined))\n// or simply\nclient.compose(interceptors.cache())","handlingStrategy":"type-guard","validationCode":"const cacheOpts = (typeof cfg === 'object' && cfg !== null) ? cfg : undefined\nclient.compose(interceptors.cache(cacheOpts))","typeGuard":"function isCacheOpts(v) { return v == null || (typeof v === 'object' && !Array.isArray(v)) }","tryCatchPattern":"try { client.compose(interceptors.cache(opts)) } catch (e) { if (e instanceof TypeError && /opts to be an Object/.test(e.message)) { client.compose(interceptors.cache()) } else throw e }","preventionTips":["Omit the argument to use defaults.","Normalize config with ?? undefined before forwarding.","Guard typeof at the boundary."],"tags":["undici","http","cache","interceptor","configuration","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}