GraphiteEditor/Graphite · error

Precache fetch failed for ${entry.url}: ${response.status}

Error message

Precache fetch failed for ${entry.url}: ${response.status}

What it means

During service-worker install, every URL in PRECACHE_MANIFEST (JS, Wasm, index.html, favicons — placeholders injected by vite.config.ts at build time) is fetched; any non-ok response aborts the Promise.all, which rejects event.waitUntil and fails installation. The new service worker never activates, so clients stay on the previous version or end up with no worker at all.

Source

Thrown at frontend/src/service-worker.js:62

		const cached = await cache.match(request);
		if (cached) return cached;
		throw new Error(`Network request failed and no cache available for ${request.url}`);
	}
}

// ================
// Lifecycle events
// ================

self.addEventListener("install", (event) => {
	event.waitUntil(
		(async () => {
			// Precache app shell assets
			const cache = await caches.open(STATIC_CACHE_NAME);
			await Promise.all(
				PRECACHE_MANIFEST.map(async (entry) => {
					const response = await fetch(entry.url);
					if (!response.ok) throw new Error(`Precache fetch failed for ${entry.url}: ${response.status}`);
					// Strip the `redirected` flag which causes errors when served via respondWith
					const cleaned = response.redirected
						? new Response(response.body, {
								status: response.status,
								statusText: response.statusText,
								headers: response.headers,
							})
						: response;
					await cache.put(entry.url, cleaned);
				}),
			);

			// Proactively cache the font catalog API
			try {
				const fontResponse = await fetch(FONT_LIST_API);
				if (fontResponse.ok) {
					const fontCache = await caches.open(RUNTIME_FONTS);
					await fontCache.put(FONT_LIST_API, fontResponse);

View on GitHub (pinned to c507b35645)

Solutions

  1. Open the failing entry.url from the error message in a browser or curl and confirm the status — this pinpoints the missing asset
  2. Rebuild and redeploy so PRECACHE_MANIFEST is generated from the exact asset set that ships (every hashed file present on the server)
  3. If clients hold a stale manifest, bumping SERVICE_WORKER_CONTENT_HASH via a fresh deploy gives them a consistent worker+assets pair
  4. Fetch with { cache: "reload" } and/or retry transient failures once during install instead of failing the entire install

Example fix

// before
const response = await fetch(entry.url);
if (!response.ok) throw new Error(`Precache fetch failed for ${entry.url}: ${response.status}`);

// after: bypass stale HTTP cache and retry transient failures once
async function fetchEntry(url) {
	for (let attempt = 0; attempt < 2; attempt += 1) {
		try {
			const r = await fetch(url, { cache: "reload" });
			if (r.ok) return r;
		} catch { /* retry */ }
	}
	return fetch(url, { cache: "reload" });
}
const response = await fetchEntry(entry.url);
if (!response.ok) throw new Error(`Precache fetch failed for ${entry.url}: ${response.status}`);
Defensive patterns

Strategy: retry

Validate before calling

// Pre-deploy smoke check: every precache URL must return 200
import { readFileSync } from "node:fs";
const manifest = JSON.parse(readFileSync("dist/sw-manifest.json", "utf8"));
for (const { url } of manifest) {
	const res = await fetch(new URL(url, base).href);
	if (!res.ok) throw new Error(`Missing precache asset: ${url} (${res.status})`);
}

Try / catch

// Per-entry catch that logs the entry, then rethrows so install still fails loudly
PRECACHE_MANIFEST.map(async (entry) => {
	try { /* fetch + cache.put */ } catch (e) {
		console.error(`Precache failed for ${entry.url}`, e);
		throw e;
	}
});

Prevention

When it happens

Trigger: A manifest entry returns 404 — typically a hashed asset name from a build whose files were not all deployed; a host returning 401/403 for an asset; an HTTP-cached stale 404 for a previously missing file; index.html reached through a redirect chain that ends in an error status.

Common situations: Partial deploys where some dist/ artifacts (especially hashed files like the split -partN.wasm chunks referenced by the manifest) were not uploaded; serving from a subpath or wrong scope so relative manifest URLs resolve incorrectly; a CDN purge mid-deploy; stale browser HTTP cache during a service-worker update.

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/3221535dd2349b63. Report an issue: GitHub.