Skip to content

Incomplete URL in next/link crashes the app in production #66650

Description

@agurtovoy

Link to the code that reproduces this issue

https://github.com/agurtovoy/nextjs-incomplete-link-bug

To Reproduce

  1. Deploy the repo above to Vercel
  2. Open the deployed site, get Application error: a client-side exception has occurred (see the browser console for more information). (sample deployment)

Current vs. Expected behavior

Current: passing incomplete/invalid URL to next/link throws an exception on render (in production) even if the user never clicks on the link.

Expected: providing incomplete/invalid URL to next/link should never lead to an exception during rendering.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.5.0: Wed May  1 20:12:58 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6000
  Available memory (MB): 16384
  Available CPU cores: 10
Binaries:
  Node: 18.20.3
  npm: 10.7.0
  Yarn: 1.22.21
  pnpm: 7.26.3
Relevant Packages:
  next: 14.2.3 // Latest available version is detected (14.2.3).
  eslint-config-next: 14.2.3
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.4.5
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Navigation, Runtime

Which stage(s) are affected? (Select all that apply)

Vercel (Deployed), Other (Deployed)

Additional context

The offending exception is thrown by the URL constructor here (while preparing to prefetch the URL):

const url = new URL(addBasePath(href), window.location.href)

While the URL constructor is pretty tolerant and in most cases will obediently return some sort of URL, even if you pass it arguably nonsensical args, it does throw in a couple of circumstances. One of these circumstances is an attempt to mix protocols, e.g.: new URL('http:', 'https://vercel.com').

That means something as innocent as <Link href="http:">Home</Link> will currently throw on render in production.

Note that because prefetching is unconditionally disabled in dev, it's easy to ship a broken site w/o knowing it.

Also note that there is other prefetching code elsewhere in the codebase (e.g. page router) where the assumption seems to be that the URL constructor doesn't throw.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Linking and NavigatingRelated to Next.js linking (e.g., <Link>) and navigation.RuntimeRelated to Node.js or Edge Runtime with Next.js.bugIssue was opened via the bug report template.locked

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions