fix: stop og and llms.mdx routes from caching made-up paths - #16
Merged
Merged
Conversation
The og handler looks a page up with the last slug segment dropped, so a request like /og/setup/anything.png rendered Setup's image and stored a new copy under the requested name. Next never evicts those files, so every made-up name grew the cache for good. Unknown pages failed to store and logged a cache-write warning on every request. Every image is generated at build time, so set dynamicParams = false: anything else now 404s before the handler runs and nothing is written. The standalone smoke run now snapshots the cache directory before the server starts and fails if any request added a path. It probes a made-up og file name and an unknown og page, and fails on the cache-write warning.
The markdown handler has the same shape as the og one: it looks a page up with the last slug segment dropped, so /llms.mdx/setup/anything.md served Setup's markdown and stored a copy under the requested name. Its optional catch-all also matched bare /llms.mdx and /llms.mdx/setup, which served the index page's markdown and stored that too. Every markdown file is generated at build time, so set dynamicParams = false. The canonical files and the root markdown rewrite are unaffected; every other path now 404s without writing. The standalone smoke run probes a made-up file name, bare /llms.mdx and an unknown page, and the existing cache-tree check covers the disk side.
The request probes only cover routes someone remembered to probe. A new dynamic route without dynamicParams = false would render any params it matches on demand and store each result on disk, and nothing would notice until the cache grew. Before the server starts, the smoke run now reads the standalone build's prerender manifest and fails on any dynamic route whose fallback is not false, naming each one. That is the field the server consults at request time, so the check holds for every route, probed or not. The header comment now maps the route-handler guard to the checks that cover it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why the change
The og and llms.mdx route handlers rendered and saved a new file for any made-up name under a real page (such as
/og/setup/anything.png), and Next never deletes those files, so scanners could fill the disk; now both routes serve only what the build generated, and CI fails if a request adds a cache file or if any dynamic route can render on demand.Special things to note
/llms.mdxand/llms.mdx/setup, which both served the index page's markdown. Nothing on the site links to them. Page metadata builds these URLs withgetPageImage/getPageMarkdownUrl, and the proxy's markdown rewrites end incontent.md. Unknown paths under both prefixes now get the HTML not-found page withCache-Control: no-storeinstead of an empty 404.Error: Internal: NoFallbackErrorstack. The handler itself rejects without logging, but Next then tries the next matching route, the[[...slug]]page, and that rejection is what gets logged. Unknown pages have logged the same line since fix: stop encoded probes from poisoning the robots.txt cache #15 (upstream: NoFallbackError logged to console.error when dynamicParams = false rejects a param vercel/next.js#90537). It replaces theFailed to update prerender cachewarning that unknown og and llms.mdx pages used to print on every request.dynamicParams = false. If a future route really needs on-demand rendering, it has to be exempted in that check on purpose.Change outline
Both handlers look a page up with the last slug segment dropped, so any file name under a real page resolved to that page. The fix is
dynamicParams = false, the same guard #15 put on the page catch-all. With it, the build marks both routesfallback: false:What that does to a made-up path:
The
if (!page) notFound()checks stay. TypeScript needs them to narrowpage, andnext dev, which has no prerender manifest, still relies on them for its 404.CI runs
scripts/smoke-standalone.tsagainst both the public and the preview build. The script gains two checks on the whole build and a probe for each URL shape:The tree check catches writes nobody predicted, and the manifest check covers routes that no probe requests.