nodejs/node · error · TypeError
expected key to be object, got ${typeof key}
Error message
expected key to be object, got ${typeof key} What it means
Thrown by MemoryCacheStore.delete() when the supplied key is not an object. The interceptor's cache key is a structured object carrying at least origin and path (delete composes `${key.origin}:${key.path}` as the top-level lookup), so a primitive cannot be used. It is a TypeError because the contract of the store API was violated, not a network/runtime failure.
Source
Thrown at deps/undici/src/lib/cache/memory-cache-store.js:207
}
// Reset the event flag after eviction
if (store.#size < store.#maxSize && store.#count < store.#maxCount) {
store.#hasEmittedMaxSizeEvent = false
}
}
callback(null)
}
})
}
/**
* @param {CacheKey} key
*/
delete (key) {
if (typeof key !== 'object') {
throw new TypeError(`expected key to be object, got ${typeof key}`)
}
const topLevelKey = `${key.origin}:${key.path}`
for (const entry of this.#entries.get(topLevelKey) ?? []) {
this.#size -= entry.size
this.#count -= 1
}
this.#entries.delete(topLevelKey)
}
}
function findEntry (key, entries, now) {
for (let i = 0; i < entries.length; i++) {
const entry = entries[i]
if (
entry.deleteAt > now &&
entry.method === key.method &&View on GitHub (pinned to 1b2de5e052)
Solutions
- Pass an object containing at least origin and path, e.g. delete({ origin: 'https://example.com', method: 'GET', path: '/users' }).
- If you hold a Request/URL, build the key from url.origin + url.pathname + url.search before calling delete.
- If integrating with the CacheInterceptor, never call store methods yourself — let the interceptor build the key.
- Add a typeof key === 'object' guard in your wrapper to fail loudly before reaching the store.
Example fix
// before
store.delete('https://example.com/users')
// after
store.delete({
origin: 'https://example.com',
method: 'GET',
path: '/users'
}) Defensive patterns
Strategy: type-guard
Validate before calling
if (key == null || typeof key !== 'object' || typeof key.origin !== 'string' || typeof key.path !== 'string') {
throw new TypeError('cache key must be an object with origin and path strings')
}
store.delete(key) Type guard
function isCacheKey(k) {
return k != null && typeof k === 'object'
&& typeof k.origin === 'string'
&& typeof k.path === 'string'
&& typeof k.method === 'string'
} Try / catch
try {
store.delete(key)
} catch (err) {
if (err instanceof TypeError && /expected key to be object/.test(err.message)) {
log.warn('skipping cache delete: malformed key', key)
} else {
throw err
}
} Prevention
- Never call store.delete/create/read directly — go through the CacheInterceptor.
- Centralize CacheKey construction in one helper that always returns an object.
- Add a TypeScript type annotation matching the CacheKey interface.
- Unit-test your cache wrapper with string and null inputs.
When it happens
Trigger: Calling memoryCacheStore.delete('http://x/y') with a string, a number, null, undefined, or a boolean instead of an object like { origin, method, path }. Reproduces in the cache-interceptor internals if a custom store wrapper forwards the wrong shape.
Common situations: Custom CacheStore implementations that pass the request URL string directly; migrating from a string-keyed cache; refactoring that drops the key object; tests that call delete() with a primitive for convenience.
Related errors
- expected key to be object, got ${typeof key}
- MemoryCacheStore options must be an object
- MemoryCacheStore options.maxCount must be a non-negative int
- MemoryCacheStore options.maxSize must be a non-negative inte
- MemoryCacheStore options.maxEntrySize must be a non-negative
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/4352c1db7ad50f15.
Report an issue: GitHub.