nodejs/node · error · TypeError

expected type of opts to be an Object, got ${opts === null ?

Error message

expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}

What it means

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'.

Source

Thrown at deps/undici/src/lib/interceptor/cache.js:511

  sendCachedValue(handler, opts, result, age, null, false)
}

/**
 * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions} [opts]
 * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor}
 */
module.exports = (opts = {}) => {
  const {
    store = new MemoryCacheStore(),
    methods = ['GET'],
    cacheByDefault = undefined,
    type = 'shared',
    origins = undefined
  } = opts

  if (typeof opts !== 'object' || opts === null) {
    throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`)
  }

  assertCacheStore(store, 'opts.store')
  assertCacheMethods(methods, 'opts.methods')
  assertCacheOrigins(origins, 'opts.origins')

  if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') {
    throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`)
  }

  if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') {
    throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`)
  }

  const globalOpts = {
    store,
    methods,
    cacheByDefault,

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Pass an object or omit the argument entirely: interceptors.cache() uses defaults.
  2. Normalize at the call site: const opts = config ?? undefined before composing.
  3. Guard with typeof before forwarding dynamic config.

Example fix

// before
client.compose(interceptors.cache(maybeConfig)) // maybeConfig can be null

// after
client.compose(interceptors.cache(maybeConfig ?? undefined))
// or simply
client.compose(interceptors.cache())
Defensive patterns

Strategy: type-guard

Validate before calling

const cacheOpts = (typeof cfg === 'object' && cfg !== null) ? cfg : undefined
client.compose(interceptors.cache(cacheOpts))

Type guard

function isCacheOpts(v) { return v == null || (typeof v === 'object' && !Array.isArray(v)) }

Try / catch

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 }

Prevention

When it happens

Trigger: Calling interceptors.cache(null), interceptors.cache(false), interceptors.cache('shared'), or interceptors.cache(somePrimitive) explicitly.

Common situations: 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.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/205243b89f20967a. Report an issue: GitHub.