{"record":{"id":"11d01211383cf510","repo":"nodejs/node","slug":"expected-opts-type-to-be-shared-private-or-undef","errorCode":null,"errorMessage":"expected opts.type to be shared, private, or undefined, got ${typeof type}","messagePattern":"expected opts\\.type to be shared, private, or undefined, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/interceptor/cache.js","lineNumber":523,"sourceCode":"    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,\n    type\n  }\n\n  const safeMethodsToNotCache = []\n  for (let i = 0; i < util.safeHTTPMethods.length; i++) {\n    const method = util.safeHTTPMethods[i]\n    if (!arrayIncludes(methods, method)) {\n      safeMethodsToNotCache.push(method)\n    }\n  }\n\n  return dispatch => {","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/interceptor/cache.js#L505-L541","documentation":"Thrown by the cache() interceptor factory when opts.type is present but is neither 'shared' nor 'private'. type controls shared vs private cache semantics (RFC 9111): 'shared' treats the cache like a shared proxy, 'private' like a single-user cache. Any other value (including typos, 'public', or booleans) is rejected; omit the option to use the default 'shared'.","triggerScenarios":"Passing type: 'public' (common confusion with private), type: 'PRIVATE' (case sensitivity), type: true, or any other invalid value.","commonSituations":"Misremembering the option name (public vs private); uppercase config values from env; copy-pasting a value from a different caching library.","solutions":["Use exactly 'shared' or 'private', or omit the option for the default 'shared'.","Normalize env-sourced values: lowercase and validate against the allow-list.","Remember: 'private' means browser/single-user semantics; there is no 'public' option here."],"exampleFix":"// before\nclient.compose(interceptors.cache({ type: 'public' }))\n\n// after\nclient.compose(interceptors.cache({ type: 'private' }))\n// or rely on the default\nclient.compose(interceptors.cache())","handlingStrategy":"validation","validationCode":"function resolveCacheType(v) {\n  if (v == null) return undefined\n  const s = String(v).toLowerCase()\n  return s === 'shared' || s === 'private' ? s : undefined\n}","typeGuard":"function isCacheType(v) { return v == null || v === 'shared' || v === 'private' }","tryCatchPattern":"try { client.compose(interceptors.cache({ type })) } catch (e) { if (e instanceof TypeError && /opts\\.type/.test(e.message)) { client.compose(interceptors.cache({ type: resolveCacheType(type) })) } else throw e }","preventionTips":["Use exactly 'shared' or 'private'.","There is no 'public' value; omit for the 'shared' default.","Lowercase + validate env-sourced values."],"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"}