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 SqliteCacheStore.delete() when the supplied key is not an object. The store expects a CacheKey (the typed import is import('../../types/cache-interceptor.d.ts').default.CacheKey) and uses key fields to build the value URL via #makeValueUrl(key), so a primitive cannot work.
Source
Thrown at deps/undici/src/lib/cache/sqlite-cache-store.js:348
} else {
this.destroy()
}
callback()
},
final (callback) {
store.set(key, { ...value, body })
callback()
}
})
}
/**
* @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key
*/
delete (key) {
if (typeof key !== 'object') {
throw new TypeError(`expected key to be object, got ${typeof key}`)
}
this.#deleteByUrlQuery.run(this.#makeValueUrl(key))
}
#prune () {
if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) {
return 0
}
{
const removed = this.#deleteExpiredValuesQuery.run(Date.now()).changes
if (removed) {
return removed
}
}
{View on GitHub (pinned to 1b2de5e052)
Solutions
- Pass a CacheKey object: delete({ origin, method, path, headers }).
- If you only have a URL, parse it and assemble the key with origin + pathname.
- Drive deletes through the CacheInterceptor so the key shape is correct by construction.
- Add a typeof key === 'object' guard in your own wrapper to fail before the store.
Example fix
// before
store.delete('https://example.com/api')
// after
const u = new URL('https://example.com/api')
store.delete({ origin: u.origin, method: 'GET', path: u.pathname }) Defensive patterns
Strategy: type-guard
Validate before calling
if (key == null || typeof key !== 'object') {
throw new TypeError('cache key must be an object')
}
store.delete(key) Type guard
function isCacheKey(k) {
return k != null && typeof k === 'object'
&& typeof k.origin === 'string'
&& typeof k.method === 'string'
&& typeof k.path === 'string'
} Try / catch
try {
store.delete(key)
} catch (err) {
if (err instanceof TypeError && /expected key to be object/.test(err.message)) {
log.warn('ignoring malformed cache key', key)
} else throw err
} Prevention
- Route deletes through the CacheInterceptor.
- Centralize CacheKey construction in one helper.
- Type your key with the CacheKey interface.
- Test your wrapper with string and null inputs.
When it happens
Trigger: Calling sqliteStore.delete('https://x/y'), delete(null), delete(undefined), or delete(42). Reproduces in custom store wrappers or tests that forward a URL string instead of the structured key.
Common situations: Treating the SQLite store like a key-value map keyed by URL string; reusing a fetch Cache API mental model where the URL is the key; refactoring that loses the key object.
Related errors
- expected key to be object, got ${typeof key}
- SqliteCacheStore options must be an object
- SqliteCacheStore options.maxEntrySize must be a non-negative
- SqliteCacheStore options.maxEntrySize must be less than 2gb
- SqliteCacheStore options.maxCount must be a non-negative int
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/c442b2042aab78d6.
Report an issue: GitHub.