Skip to content

Client route parameterization names everything /:lng/:notFound* when the locale param is [lng] and the default locale has no URL prefix #23488

Description

@otaviosoares

Is there an existing issue for this?

How do you use Sentry?

Self-hosted / on-premise

Which SDK are you using?

@sentry/nextjs

SDK Version

10.70.0

Framework Version

Next.js 16.2.6 (App Router)

Link to Sentry event

(self-hosted)

Steps to Reproduce

Our app dir uses [lng] as the locale param (i18next convention), with a catch-all for hard 404s:

app/
  [lng]/
    page.tsx
    guides/[category]/[...rest]/page.tsx
    [...notFound]/page.tsx

The default locale is served without a prefix: /guides/renting/foo for en, /fr/guides/renting/foo for fr.

Build with route manifest injection enabled (the default) and load any default-locale page with 2+ path segments.

Expected Result

/guides/renting/foo gets named /:lng/guides/:category/:rest*, same as the prefixed locales.

Actual Result

It gets named /:lng/:notFound*. Same for basically every unprefixed URL with 2+ segments, so most of our traffic (default locale) reports transactions and error culprits pointing at the 404 catch-all.

Cause: findMatchingRoutes has a retry that prepends SENTRY_OPTIONAL_PREFIX for exactly this unprefixed-default-locale case, but it only runs for routes with hasOptionalPrefix, and createRouteManifest.ts only sets that flag when the first param is literally locale, lang or language:

// packages/nextjs/src/config/manifest/createRouteManifest.ts
function hasOptionalPrefix(paramNames: string[]): boolean {
  const firstParam = paramNames[0];
  ...
  return firstParam === 'locale' || firstParam === 'lang' || firstParam === 'language';
}

lng isn't in the list, even though it's i18next's own option name and the folder name used in the next-i18next examples. So for [lng] projects the regexes never match unprefixed paths and the catch-all wins. Only workaround right now is routeManifestInjection: false, which drops parameterization entirely.

Proposed fix

Add 'lng' to the list, and/or make it configurable. Already raised in the #17927 description:

Maybe we should make certain aspects of this configurable, like the ['locale', 'lang', 'language'] collection

e.g.:

routeManifestInjection: {
  localeParamNames: ['lng']
}

Can open a PR for either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions