vuejs/vue · error · Error
renderer cache must implement at least get & set.
Error message
renderer cache must implement at least get & set.
What it means
Thrown by the RenderContext constructor when the cache option is truthy but is missing either a get or a set method. The renderer's component caching mechanism calls cache.get and cache.set during renderComponentWithCache, so both must exist. A partial cache object (e.g. only has get, or is a plain object) is rejected because silent cache misses would degrade SSR performance without warning.
Source
Thrown at packages/server-renderer/src/render-context.ts:62
get?: (key: string, cb: Function) => void
has?: (key: string, cb: Function) => void
constructor(options: Record<string, any>) {
this.userContext = options.userContext
this.activeInstance = options.activeInstance
this.renderStates = []
this.write = options.write
this.done = options.done
this.renderNode = options.renderNode
this.isUnaryTag = options.isUnaryTag
this.modules = options.modules
this.directives = options.directives
const cache = options.cache
if (cache && (!cache.get || !cache.set)) {
throw new Error('renderer cache must implement at least get & set.')
}
this.cache = cache
this.get = cache && normalizeAsync(cache, 'get')
this.has = cache && normalizeAsync(cache, 'has')
this.next = this.next.bind(this)
}
next() {
// eslint-disable-next-line
while (true) {
const lastState = this.renderStates[this.renderStates.length - 1]
if (isUndef(lastState)) {
return this.done()
}
/* eslint-disable no-case-declarations */
switch (lastState.type) {
case 'Element':View on GitHub (pinned to 9e88707940)
Solutions
- Ensure the cache object implements both get(key, cb?) and set(key, val) as methods.
- Wrap external caches (Redis, LRU) in an adapter: { get: (k, cb) => redis.get(k, cb), set: (k, v) => redis.set(k, v) }.
- Pass undefined/null instead of a partial object if caching is not needed.
- Use lru-cache with a compatible adapter or the built-in pattern from Vue SSR docs.
Example fix
// before — raw object with no get/set
createRenderer({ cache: { ttl: 600 } })
// after — proper cache adapter
const LRU = require('lru-cache')
const lru = new LRU({ max: 1000, maxAge: 1000 * 60 * 15 })
createRenderer({
cache: {
get: (key, cb) => cb(lru.get(key)),
set: (key, val) => lru.set(key, val),
has: (key, cb) => cb(lru.has(key))
}
}) Defensive patterns
Strategy: type-guard
Validate before calling
function isValidCache(cache: unknown): boolean {
if (!cache) return true // no cache is valid
return typeof (cache as any).get === 'function' && typeof (cache as any).set === 'function'
}
if (!isValidCache(options.cache)) {
throw new Error('cache must have get and set methods')
}
createRenderer(options) Type guard
type RenderCache = { get: (key: string, cb?: Function) => any; set: (key: string, val: string) => void; has?: (key: string, cb?: Function) => any }
function isRenderCache(v: unknown): v is RenderCache {
if (typeof v !== 'object' || v === null) return false
const c = v as Record<string, unknown>
return typeof c.get === 'function' && typeof c.set === 'function'
} Try / catch
// Thrown in RenderContext constructor, called synchronously inside render().
// Wrap the render call:
try {
renderer.renderToString(app, cb)
} catch (e) {
if (e.message.includes('renderer cache must implement')) {
console.error('Fix cache adapter or remove the cache option')
}
throw e
} Prevention
- Wrap external stores (Redis, Memcached) in an explicit { get, set, has } adapter before passing.
- Do not pass configuration objects (e.g. { ttl }) as the cache; pass the adapter instance.
- Unit-test the cache adapter to confirm get/set exist and return expected shapes.
- If caching is optional, default the cache option to undefined, not to a partial object.
When it happens
Trigger: Calling createRenderer({ cache: someObject }) where someObject is truthy but lacks a get or set function. Typical with a half-implemented cache adapter, a plain Map passed wrongly (Map has get/set but they are prototype methods — still works), or a config object that was meant to configure a cache but was passed as the cache itself.
Common situations: Passing a Redis client object directly instead of wrapping it in a { get, set } adapter. Passing a configuration object { ttl: 1000 } by mistake. Using a stale cache API from an older version that had different method names.
Related errors
- Invalid JSON bundle file: ${bundle}
- Cannot locate bundle file: ${bundle}
- Invalid server-rendering bundle format. Should be a string o
- [@vue/compiler-sfc] SFC contains no <script> tags.
- \n\nVue packages version mismatch:\n\n- vue@${vueVersion}\n-
AI-assisted analysis of vuejs/vue@9e88707940 (2026-08-11).
Data as JSON: /api/errors/e2a802c89de2e122.
Report an issue: GitHub.