Skip to content

JavaScript Cache API Not Storing Response Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about JavaScript Cache API Not Storing Response Fix. We cover key concepts, practical examples, and best practices.

The Problem

The Cache API silently fails to store responses when the response body has already been consumed, when the response is an opaque response from a different origin, or when storage limits are exceeded. You fetch data but the cache stays empty.

Quick Fix

Step 1: Clone response before caching

// Wrong — response body consumed by json(), then cache gets empty body
const response = await fetch('/api/data');
const data = await response.json();
await caches.open('v1').then(cache => cache.put('/api/data', response));

// Right — clone the response
const response = await fetch('/api/data');
const cache = await caches.open('v1');
cache.put('/api/data', response.clone()); // clone before reading
const data = await response.json();

Step 2: Handle opaque responses

// Wrong — opaque responses (no-cors) have status 0 and empty body
const response = await fetch('https://other-origin.com/image.png', {
    mode: 'no-cors'
});
const cache = await caches.open('v1');
cache.put('/external-image', response);
// Cache.put() fails silently for opaque responses

// Right — only cache same-origin or CORS responses
const response = await fetch('https://other-origin.com/image.png');
if (response.type === 'opaque') {
    // Cannot reliably cache opaque responses
    console.warn('Opaque response cannot be cached');
} else {
    const cache = await caches.open('v1');
    cache.put('/external-image', response);
}

Step 3: Check storage quota before caching

async function cacheWithQuotaCheck(url) {
    const estimate = await navigator.storage.estimate();
    const available = estimate.quota - estimate.usage;

    const response = await fetch(url);
    const cloned = response.clone();
    const size = parseInt(cloned.headers.get('content-length') || '0');

    // Wrong — ignores storage limits
    // (await caches.open('v1')).put(url, cloned);

    // Right — check quota first
    if (size > available) {
        console.warn('Not enough storage to cache:', url);
        return response;
    }

    const cache = await caches.open('v1');
    await cache.put(url, cloned);
    return response;
}

Step 4: Use Cache API in service worker properly

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((cached) => {
            // Wrong — returns cached and fetches without updating cache
            return cached || fetch(event.request);

            // Right — cache then network strategy
            const fetchPromise = fetch(event.request).then((response) => {
                const clone = response.clone();
                caches.open('v1').then(cache => cache.put(event.request, clone));
                return response;
            });
            return cached || fetchPromise;
        })
    );
});

Prevention

  • Always clone Response objects before caching — you cannot reuse a consumed body
  • Check response.type !== 'opaque' before caching cross-origin resources
  • Monitor storage usage with navigator.storage.estimate()
  • Delete old caches during service worker activation to free space
  • Use the Cache API only within secure contexts (HTTPS or localhost)

Common Mistakes with web api cache

  1. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  2. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  3. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks

These mistakes appear frequently in real-world JS code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Why does Cache.put() return undefined even on success?

Cache.put() returns a Promise that resolves with undefined. It does not return the cached response. Use cache.match(key) to verify the entry was stored. If it returns undefined, the put failed silently.

Can I cache POST requests?

Yes, but the Cache API caches the full Request/Response pair including headers. POST requests are matched by URL + VARY headers. Most service worker patterns cache only GET requests for simplicity.

What is the storage limit for Cache API?

Storage limits follow the browser's storage quota. On desktop, typically ~60% of available disk. On mobile, less. Use navigator.storage.estimate() and navigator.storage.persist() to manage and persist storage.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro