withastro/astro · warning

[astro:cache] Background revalidation failed for ${requestUr

Error message

[astro:cache] Background revalidation failed for ${requestUrl.pathname}${requestUrl.search}: ${String(error)}

What it means

Astro's experimental in-memory cache serves entries past max-age while `staleWhileRevalidate` permits it, returning the STALE copy immediately (X-Astro-Cache: STALE) and refreshing in the background. If that background revalidation fetch to your origin rejects — network error, DNS failure, upstream 5xx thrown by the cached function — this warning prints the URL and error. The current visitor already got the stale copy, so nothing user-facing failed; the next request simply retries revalidation.

Source

Thrown at packages/astro/src/core/cache/memory-provider.ts:470

										return;
									}
									const newTags = parseCacheTags(freshResponse.headers.get('Cache-Tag'));
									const newEntry = await serializeResponse(
										freshResponse,
										context.request,
										newMaxAge,
										newSwr,
										newTags,
									);
									// Update Vary map if the response changed its Vary headers
									if (newEntry.vary) {
										varyMap.set(primaryKey, newEntry.vary);
									}
									cache.set(key, newEntry);
								}
							})
							.catch((error) => {
								console.warn(
									`[astro:cache] Background revalidation failed for ${requestUrl.pathname}${requestUrl.search}: ${String(
										error,
									)}`,
								);
							});

						const response = createResponseFromCacheEntry(cached);
						response.headers.set('X-Astro-Cache', 'STALE');
						return response;
					}
				}

				// Past SWR window or Vary mismatch — expired, treat as miss
			}

			// Cache miss — render fresh
			const response = await next();

View on GitHub (pinned to 3578d45d34)

Solutions

  1. Verify the origin URL from the message with curl — the warning mirrors upstream availability
  2. Treat it as transient noise during upstream incidents: stale content keeps serving, which is the feature working
  3. Harden the cached fetcher (timeout + one retry) so transient origin blips don't log at all
  4. Revisit expiresIn/staleWhileRevalidate windows if your origin is too flaky to revalidate reliably
Defensive patterns

Strategy: retry

Try / catch

// Endpoints: degrade gracefully when even the cache layer is unhealthy
export const GET = async ({ cache }) => {
  try {
    return await cache('products', () => fetch(PRODUCTS_API), {
      expiresIn: 60,
      staleWhileRevalidate: 3600,
    });
  } catch {
    return new Response('upstream unavailable', { status: 503 });
  }
};

Prevention

When it happens

Trigger: Using `cache(key, fetcher, { expiresIn, staleWhileRevalidate })` where the fetcher rejects after the entry has gone stale — upstream unreachable, DNS failure, or the handler throws while refreshing.

Common situations: Dev machine briefly offline; upstream API having an incident while the cache keeps serving stale data; aggressive revalidation during cold starts; CI environments without network egress.

Related errors


AI-assisted analysis of withastro/astro@3578d45d34 (2026-08-18). Data as JSON: /api/errors/0c3fe9d9f22a4e24. Report an issue: GitHub.