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

  1. Pass a CacheKey object: delete({ origin, method, path, headers }).
  2. If you only have a URL, parse it and assemble the key with origin + pathname.
  3. Drive deletes through the CacheInterceptor so the key shape is correct by construction.
  4. 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

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


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