workerd: cache API put failed, cache unavailable in workerd
Fixes cache API put failures where the Cache API is unavailable or cache.put rejects in a Cloudflare Worker. Use it when caching code works in one context but fails in another, for example deployed on a custom domain versus local dev or a workers.dev subdomain. Key trigger: caches.default behaving differently across contexts while a named cache created with caches.open works everywhere.
TL;DR: caches.default only gets full edge backing on a zone route (your own domain on the account). On workers.dev or in some local contexts it is limited or absent, so cache.put can fail. Use a named cache from caches.open for behavior that works everywhere, and check that your put meets the cacheability rules.
workerd: cache API put failed, cache unavailable in workerd- Identify where the worker runs. Check your routes: is the worker attached to a custom domain route on your account, or only on a workers.dev subdomain?
Expected: you know which context the failing code runs in.
- Check the put preconditions in your code. The request being cached must be a GET, and the response must be cacheable (a cacheable status, no conflicting directives that forbid storing it).
Expected: you can point at the request method and response headers and confirm they allow caching.
- Switch the failing path to a named cache, which is available in every context:
const cache = await caches.open("my-app-cache");
await cache.put(request, response);Expected: the put succeeds in local dev, on workers.dev, and on the custom domain.
- If you specifically need caches.default edge behavior, move that code path behind a zone route on your own domain and retest.
Expected: cache.put against caches.default succeeds when the request flows through the zone.
- In local dev, rerun with
wrangler devand confirm the same code path caches and serves hits.
Expected: repeated requests hit the cached response instead of recomputing it.
Use this when
- cache.put throws or silently does nothing in one environment but not another
- caches.default works on your custom domain but fails on workers.dev or in local dev
- you are caching API responses or HTML inside a worker and need consistent behavior
- the failure appeared after moving the worker from a zone route to workers.dev
Not for this skill when
- you are trying to purge or inspect the Cloudflare CDN cache from the dashboard (different feature)
- the problem is stale content being served (that is TTL and revalidation, not put failing)
- cache.match returns misses because the cache key differs per request (key normalization issue)
- you need cross-worker shared caching with strong consistency (look at KV or D1 instead)
Variant phrasings
- caches.default not available in worker
- Cloudflare Worker cache.put throws
- cache API unavailable in workerd local dev
- workers.dev cache.put fails but custom domain works
- Cache API put rejected in Cloudflare Worker
Why it happens
caches.default is tied to the edge cache of a zone, so it only has full backing when the worker handles requests on a domain in your account. Outside that context the default cache is limited or unavailable, and puts fail. A named cache from caches.open is a separate storage namespace that workerd provides in every context, which is why switching to one fixes the inconsistency.
Edge cases
- Responses with Set-Cookie or certain auth headers are not stored. Strip or vary on them deliberately.
- Only GET requests are cached. A POST to the same URL will never hit the cache.
- Large objects can be rejected. Keep cached bodies within the documented object size limits or store big blobs in R2 and cache a pointer.
- In local dev the cache does not persist across restarts unless you pass the persist flag, so a "cold" local cache after every restart is normal.
- Cache keys include the full URL. Query-string ordering differences cause misses that look like put failures.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_AMwwzSZ6nBabHxjyfbD28Q
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.