v156 · failure taxonomy

What stays cached

"Avoid caching module failures" is narrower than its name: only network and HTTP-status failures become retryable. A module that arrives fine but fails to parse is still cached — refetching identical broken bytes would help nobody — and successful modules were always cached. Three modules, two imports each, and the fetch counts tell the three categories apart.

Import each category twice

Each run imports three URLs twice each: one that 404s, one that is served (HTTP 200, JavaScript MIME type) but contains a syntax error, and one healthy module. Fetches are counted from the Resource Timing buffer.
Two import() calls per module, and what the network saw
module import #1 import #2 network fetches this browser's behaviour
missing
(HTTP 404)
not run
parse error
(HTTP 200, broken source)
not run
healthy
(HTTP 200, valid module)
not run

Where the spec draws the line

In the HTML Standard's fetch a single module script, the module map entry is removed when the response body is null/failure or the status is not ok — that is the whole change. A response that decodes but does not parse still produces a module script (whose error is rethrown on every use), and that script is stored, so retries of a parse error reject without refetching in every Chrome. Expected counts:

Expected network fetches for two import() calls
categorypre-156Chrome 156+why
404 / network failure12failure entry now removed from the module map
parse error11an errored module script is still a cached script
success11successful modules were always cached

Both failing categories keep rejecting on every import — a 404 with TypeError: Failed to fetch dynamically imported module, the parse error with its SyntaxError. Only the row where the counts differ is new.

see also