Feature/Bug
stale-if-error (both the response and request directive) is honored when the origin responds
with 500/502/503/504 (allowErrorStatusCodes check, lib/handler/cache-revalidation-handler.js:72-73),
but when the origin is unreachable, onResponseError fails the request outright
(cache-revalidation-handler.js:106-121) even when a within-threshold stale entry exists.
RFC 5861 §4 defines an error as "any situation that would result in a 500, 502, 503 or 504" —
for a client-side cache, failing to connect is the situation a gateway would surface as
502/504, and resilience across origin outages is the extension's headline use case (nginx
proxy_cache_use_stale error ..., Varnish, Fastly all treat connect errors this way).
Repro: store 200 Cache-Control: max-age=1, stale-if-error=60; stop the origin; wait past
staleness; request again → observed ECONNREFUSED thrown (undici 8.7.0, current main, Node 22);
expected: stale cached response served. The equivalent test with the origin returning 503 works
today, which makes the inconsistency surprising.
Suggested fix
In CacheRevalidationHandler.onResponseError, when #allowErrorStatusCodes (the caller already
encodes the within-stale-if-error-threshold decision, interceptor/cache.js:346-350) and no
response has started, invoke the callback with success so the interceptor serves the stale entry;
propagate the error only otherwise. ~20-40 LOC + tests.
Found during an agent-assisted HTTP-caching review for @jeswr; every claim reproduced on undici 8.6.0 (repo) and 8.7.0 (npm) on Node 22.23.1. Fix PR to follow.
Feature/Bug
stale-if-error(both the response and request directive) is honored when the origin respondswith 500/502/503/504 (
allowErrorStatusCodescheck, lib/handler/cache-revalidation-handler.js:72-73),but when the origin is unreachable,
onResponseErrorfails the request outright(cache-revalidation-handler.js:106-121) even when a within-threshold stale entry exists.
RFC 5861 §4 defines an error as "any situation that would result in a 500, 502, 503 or 504" —
for a client-side cache, failing to connect is the situation a gateway would surface as
502/504, and resilience across origin outages is the extension's headline use case (nginx
proxy_cache_use_stale error ..., Varnish, Fastly all treat connect errors this way).Repro: store
200 Cache-Control: max-age=1, stale-if-error=60; stop the origin; wait paststaleness; request again → observed
ECONNREFUSEDthrown (undici 8.7.0, current main, Node 22);expected: stale cached response served. The equivalent test with the origin returning 503 works
today, which makes the inconsistency surprising.
Suggested fix
In
CacheRevalidationHandler.onResponseError, when#allowErrorStatusCodes(the caller alreadyencodes the within-stale-if-error-threshold decision, interceptor/cache.js:346-350) and no
response has started, invoke the callback with success so the interceptor serves the stale entry;
propagate the error only otherwise. ~20-40 LOC + tests.
Found during an agent-assisted HTTP-caching review for @jeswr; every claim reproduced on undici 8.6.0 (repo) and 8.7.0 (npm) on Node 22.23.1. Fix PR to follow.