vercel / vercel/next.js

next/font/google: a 404 on a font file is reported as "Module not found" and never retried

Open
#97,378 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
142k
Forks
32.5k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Link to the code that reproduces this issue

https://github.com/lucasmcht-corp/next-font-404-repro

To Reproduce
git clone https://github.com/lucasmcht-corp/next-font-404-repro
cd next-font-404-repro
npm install
npm run build:mocked

The build exits 1 with:

Received response with status 404 when requesting https://fonts.gstatic.com/s/bitter/v42/this-file-does-not-exist.woff2
> Build error occurred
Error: Module not found: Can't resolve '@vercel/turbopack-next/internal/font/google/font'

The stylesheet is served through Next's own NEXT_FONT_GOOGLE_MOCKED_RESPONSES hook, so no CDN behaviour is involved. It points at a font file URL that does not exist, so the file fetch, which is not mocked, answers 404 on every machine, every time.

Current vs. Expected behavior

Current: a single failed font file download stops the build with Module not found: Can't resolve '@vercel/turbopack-next/internal/font/google/font'. The HTTP status appears only as a warning earlier in the log, easily lost in a large build. There is no retry.

Expected: the fetch is retried, and if it still fails the build error names the network failure, the URL and the status code, instead of an internal module.

Where it happens

In crates/next-core/src/next_font/google/mod.rs:

Why this matters outside the mock

The same path is reached with no mock at all. On 16.3.1 our production builds failed at random, on a different family each run (Bitter, Montserrat, Noto Serif), with .next deleted before each build, because the stylesheet returned by fonts.googleapis.com pointed at files fonts.gstatic.com had already rotated away. Checked again while writing this:

URL status
.../notoserif/v33/ga63aw1J5X9T9RW6...QLqNQw.woff2 (requested by the build) 404
.../notoserif/v33/ga6daw1J5X9T9RW6...WsNFHuQk.woff2 (returned today for the same family) 200

A likely trigger, offered as a hypothesis since I could not capture the stylesheet the failing build received: fonts.googleapis.com/css2 answers with cache-control: private, max-age=86400, stale-while-revalidate=604800 and vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site. The fetcher sends no Sec-Fetch-* headers, so it addresses its own cache entry, one browsers never keep warm, which may be served stale for up to seven days while the files it names are rotated.

That hypothesis is only about what makes the fetch fail. The reproduction above is about what Next does when it does fail, which is deterministic and independent of it.

Suggested fix, in order of value
  1. Retry the font file fetch before giving up.
  2. Report the HTTP status and URL as the build error instead of a missing module.
  3. Optionally send Sec-Fetch-Dest: style on the stylesheet request, so the fetcher shares the cache entry browsers keep warm.
Related
  • #97376, same report without a reproduction, closed automatically.
  • #97344, same intermittent build failure, also closed for a missing reproduction link.
Environment
next 16.3.1
node 22.23.0
Linux x64
App Router, next/font/google

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in crates/next-core/src/next_font/google/mod.rs, reading fetch_from_google_fonts and NextFontGoogleFontFileReplacer. Run the linked reproduction with npm run build:mocked, then verify that failed font-file requests are retried and that a final failure reports the URL, HTTP status, and network error instead of an internal module resolution error.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, rust
Domain
build-system
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.