nodejs/node · error · TypeError
expected opts.cacheByDefault to be number or undefined, got
Error message
expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault} What it means
Thrown by the cache() interceptor factory when opts.cacheByDefault is present but not a number. cacheByDefault, when set, instructs the interceptor to cache responses even without explicit Cache-Control (treating them as fresh for the given number of seconds). It must be a number (seconds) or undefined; strings, booleans, etc. are rejected.
Source
Thrown at deps/undici/src/lib/interceptor/cache.js:519
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,
type
}
const safeMethodsToNotCache = []
for (let i = 0; i < util.safeHTTPMethods.length; i++) {
const method = util.safeHTTPMethods[i]
if (!arrayIncludes(methods, method)) {
safeMethodsToNotCache.push(method)View on GitHub (pinned to 1b2de5e052)
Solutions
- Pass a numeric seconds value: cacheByDefault: 60.
- Coerce strings: Number(value) and confirm Number.isFinite before passing.
- Omit the option if you only want to cache responses that carry explicit Cache-Control headers.
Example fix
// before
client.compose(interceptors.cache({ cacheByDefault: '60' }))
// after
client.compose(interceptors.cache({ cacheByDefault: 60 })) Defensive patterns
Strategy: type-guard
Validate before calling
function resolveCacheByDefault(v) {
if (v == null) return undefined
const n = Number(v)
return Number.isFinite(n) ? n : undefined
} Type guard
function isCacheByDefault(v) { return v == null || typeof v === 'number' } Try / catch
try { client.compose(interceptors.cache({ cacheByDefault })) } catch (e) { if (e instanceof TypeError && /cacheByDefault/.test(e.message)) { client.compose(interceptors.cache({ cacheByDefault: Number(cacheByDefault) || undefined })) } else throw e } Prevention
- Pass cacheByDefault as a number of seconds.
- Coerce env/config strings with Number() + isFinite.
- Omit when you only want explicit Cache-Control caching.
When it happens
Trigger: Passing cacheByDefault as a string ('60'), a boolean (true), or any non-number in cache() interceptor opts.
Common situations: Reading the TTL from config/env as a string; assuming true means 'enable'; mixing units (minutes vs seconds).
Related errors
- expected ${name} to be an array or undefined, got ${typeof o
- expected ${name}[${i}] to be a string or RegExp, got ${typeo
- expected type of opts to be an Object, got ${opts === null ?
- expected opts.type to be shared, private, or undefined, got
- expected type of opts to be an Object, got ${opts === null ?
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/38bc98e156498dbf.
Report an issue: GitHub.