fix(app-router): router.prefetch throws on invalid URL#1564
Conversation
Match Next.js's createPrefetchURL behaviour: when the href cannot be parsed via `new URL(href, window.location.href)`, throw the canonical message `Cannot prefetch '<href>' because it cannot be converted to a URL.` so the surrounding error boundary in the App Router can surface the failure instead of silently swallowing it inside the async prefetch IIFE. Closes #1553
|
/bigbonk review |
commit: |
|
There was a problem hiding this comment.
Code looks correct and well-tested. The fix mirrors createPrefetchURL from Next.js's packages/next/src/client/components/app-router-utils.ts:22-29 — same try/catch around new URL(href, window.location.href), same canonical error message.
Verified against Next.js source:
- Next.js test
test/e2e/app-dir/app-prefetch/prefetching.test.ts:469-478expectsrouter.prefetchwith an invalid URL to throw and surface via error boundary — the PR matches this behavior. - Error message
Cannot prefetch '<href>' because it cannot be converted to a URL.matches exactly. - Placement is correct: the validation runs synchronously before the async IIFE, so the throw propagates to React's error boundary instead of being swallowed by the
.catch()on line 1565.
One minor observation (not blocking): Next.js's createPrefetchURL validates new URL(addBasePath(href), ...) rather than new URL(href, ...). When basePath is non-empty, this could theoretically make a broken-looking URL parseable (e.g. new URL("/app///", origin) succeeds while new URL("///", origin) throws). This is an extremely unlikely edge case and the current implementation is correct for the default (empty basePath) and all realistic inputs. Not worth holding the PR for.
Test coverage is solid — the three cases (invalid URL throws, normal pathname works, absolute http URL works) cover the important scenarios well.
|
Review posted and approved on PR #1564. Summary: The fix is correct and well-aligned with Next.js behavior. The key change is a synchronous URL validation ( |
Closes #1553
Summary
router.prefetchnow throws the canonical Next.jsCannot prefetch '<href>' because it cannot be converted to a URL.message when given an unparseable URL, matchingcreatePrefetchURLinpackages/next/src/client/components/app-router-utils.ts.console.error("[vinext] RSC prefetch setup error:", error), so the surrounding App Router error boundary never rendered (Next.js test app<h1>A prefetch threw an error</h1>never appeared).Test plan
tests/router-prefetch-invalid-url.test.tsasserts throw with the canonical message forINVALID_URL = "///"and that normal hrefs still succeed.vp checkpasses (format + lint + typecheck on 649 files).tests/router-javascript-urls.test.tsandtests/prefetch-cache.test.tsstill pass.