Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Next.js: basePath is concatenated onto absolute router.push hrefs, corrupting navigation transaction names

Open Beginner friendly
#24,672 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active

Research direction

The issue is in the Next.js client routing instrumentation files: build/cjs/client/routing/appRouterRoutingInstrumentation.js and likely a similar file for the router-patch path. Look for the normalizedHref assignment. The fix is to guard the concatenation so it only applies to root-relative paths (those starting with '/'), mirroring Next.js's addPathPrefix logic. Test by setting up a Next.js App Router app with a basePath, using Sentry, and verifying navigation transaction names after a router.push with an absolute URL.

Written by the indexing model from the issue text.

Description

Browser Bug Next.js Traces Waiting for: Product Owner

Summary

@sentry/nextjs prepends basePath to the router.push / router.replace argument with an unguarded string concatenation. When the argument is an absolute URL, the two are glued together and the navigation span is named something like:

/hhttps://example.com/login

instead of /login. The navigation itself works correctly — only the span name is corrupted — so this shows up as junk entries in the transaction list and in dashboards, not as a user-facing failure.

Versions

  • @sentry/nextjs 10.22.0; also present in 11.0.0 (latest at time of writing)
  • next 15.5.18, App Router, basePath: '/h'
  • Affects both navigation instrumentation modes (see below)

Root cause

build/cjs/client/routing/appRouterRoutingInstrumentation.js, in the transition-start-hook path:

const basePath = process.env._sentryBasePath ?? globalWithInjectedBasePath._sentryBasePath;
const normalizedHref = basePath && !href.startsWith(basePath) ? `${basePath}${href}` : href;
const unparameterizedPathname = new URL(normalizedHref, WINDOW.location.href).pathname;

With basePath = '/h' and href = 'https://example.com/login', href.startsWith('/h') is false, so the result is '/h' + 'https://example.com/login', and new URL(...).pathname faithfully returns /hhttps://example.com/login.

The same expression appears in the router-patch path, so both modes are affected.

Note the second-order effect: an href that already carries the base path — https://example.com/h/payments — is still concatenated, because as a string it starts with https, not /h.

Why Next.js itself is unaffected

Next's own addPathPrefix guards on the leading slash:

function addPathPrefix(path, prefix) {
  if (!path.startsWith('/') || !prefix) {
    return path;
  }
  ...
}

So Next leaves absolute URLs alone, treats a same-origin absolute URL as an internal navigation, and routes correctly. Only the Sentry span name diverges from reality.

Reproduction

  1. Next.js App Router app with basePath: '/h' and @sentry/nextjs client instrumentation.
  2. Call router.push('https://<same-origin>/login') — or, more realistically, have a server component throw redirect('https://<same-origin>/login'). Next's RedirectBoundary catches it and calls router.push(url) internally, so this needs no unusual application code.
  3. Observe the resulting navigation transaction name.

Expected: /login
Actual: /hhttps://<same-origin>/login

Absolute redirect targets are not exotic in a basePath app: Next's server redirect() runs the location through addPathPrefix, so an absolute URL is the documented way to send a user to a path outside the base path. Those same absolute URLs then reach the client router whenever the redirect is hit during a soft navigation.

We see seven distinct corrupted names in production across two apps over 90 days.

Suggested fix

Mirror Next's guard — only prefix root-relative paths:

-const normalizedHref = basePath && !href.startsWith(basePath) ? `${basePath}${href}` : href;
+const normalizedHref =
+  basePath && href.startsWith('/') && !href.startsWith(basePath) ? `${basePath}${href}` : href;

Both occurrences need it. The router-patch branch additionally guards typeof href === 'string' already, which the hook branch does not.


Investigated and written with Claude Code.

Dominant language
TypeScript
Stars
8.7k
Forks
1.9k
Avg merge
1d 16h
Merged PRs (30d)
576

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.

More from getsentry/sentry-javascript

All issues in getsentry/sentry-javascript

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.