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
| 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:
| category | pre-156 | Chrome 156+ | why |
|---|---|---|---|
| 404 / network failure | 1 | 2 | failure entry now removed from the module map |
| parse error | 1 | 1 | an errored module script is still a cached script |
| success | 1 | 1 | successful 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.