Skip to content

fix(core): treat VERSION_NEUTRAL in middleware routes as no version - #17947

Merged
kamilmysliwiec merged 3 commits into
nestjs:masterfrom
Chaoqi31:fix/middleware-version-neutral
Sep 30, 2026
Merged

kamilmysliwiec merged 3 commits into
nestjs:masterfrom
Chaoqi31:fix/middleware-version-neutral

Conversation

@Chaoqi31

Copy link
Copy Markdown
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

With URI versioning, a middleware route whose version is VERSION_NEUTRAL, alone or in an array (both allowed by RouteInfo.version: VersionValue):

consumer
  .apply(LoggerMiddleware)
  .forRoutes({ path: 'cats', method: RequestMethod.GET, version: VERSION_NEUTRAL });

RouteInfoPathExtractor.extractVersionPathFrom() calls toString() on the symbol and builds /vSymbol(VERSION_NEUTRAL)/cats. Express and Fastify then fail at app.init():

TypeError: Unexpected ( at index 8: /vSymbol(VERSION_NEUTRAL)/cats; visit https://git.new/pathToRegexpError for info

exclude() takes the same path. For controllers, RoutesMapper already maps VERSION_NEUTRAL to "no version", and RoutePathFactory does not add a version segment for it.

The new specs against the current route-info-path-extractor.ts:

 × RouteInfoPathExtractor > extractPathsFrom > should not add a version segment for VERSION_NEUTRAL
 × RouteInfoPathExtractor > extractPathFrom > should not add a version segment for VERSION_NEUTRAL
AssertionError: expected [ '/vSymbol(VERSION_NEUTRAL)/cats' ] to deeply equal [ '/cats' ]

Issue Number: N/A

What is the new behavior?

extractVersionPathFrom() gives VERSION_NEUTRAL an empty version path, so the route above is /cats, and ['1', VERSION_NEUTRAL] gives /v1/cats and /cats. For a wildcard route, the exact-match $ entry is skipped when the global prefix and the version path are both empty, as the unversioned branch already does; a bare $ would otherwise match every route on Fastify.

A throwaway app with a VERSION_NEUTRAL controller and the middleware above now starts on both adapters, and GET /cats runs the middleware once.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

npx vitest run packages/core: 1396 passed.

Chaoqi31 and others added 3 commits September 30, 2026 18:50
With URI versioning, `forRoutes()` or `exclude()` with a route whose
`version` is `VERSION_NEUTRAL`, alone or in an array, built the path
from the symbol's string, `/vSymbol(VERSION_NEUTRAL)/cats`. Express
and Fastify then failed at startup, because path-to-regexp rejects
the parenthesis.

Give `VERSION_NEUTRAL` an empty version path, as controller routes
already do, and skip the exact-match entry of a wildcard route when
that leaves no base path to match.
@kamilmysliwiec
kamilmysliwiec merged commit e930053 into nestjs:master Sep 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants