Repository navigation
v12.2.0 (2026-10-19)
Notable changes
New options
@Sse({ maxPendingDataLength })sets how many characters of event data may wait for a client that is not reading its events (4M by default;0orInfinitylifts the limit) – 2f05ad954eIoAdapterandWsAdaptertakemaxConcurrentMessages, the number of a client's messages handled at once (1000 by default;Infinitylifts it) – 0bd0810ed7ValidationPipetakesmaxErrorMessagesLength(1,000,000 characters by default); messages past it are replaced by a "Further validation errors were omitted" entry – 086c1c514f- Kafka:
parser.maxMessageSize(16 MiB after decompression by default); larger messages are logged and skipped – 9bdf844fca - TCP server:
drainTimeout(30 s by default,0disables) disconnects a peer that leaves its responses unread – 583d6077ad - MQTT server:
reconnectOnConnackErroris now enabled by default, so a refused connection attempt is retried; set it tofalsefor the previous behaviour – a63cea600a HttpServer.getRouteMatchingOptions(), an optional adapter hook that tells core how the router matches paths (see "Middleware exclusions" below) – 08d8677c8d
New defaults and behaviour changes
@nestjs/platform-express,@nestjs/platform-fastify:fieldNestingDepthandfieldArrayIndexLimit(#18074) now default to 32 and 1000; set them toInfinityto lift the limits – 94fcc93770ValidationPipevalidates withvalidationError.target: falseunless the options set it, so anexceptionFactorythat readserror.targetgetsundefined; setvalidationError.targettotruefor the old errors – 8c5a59bf63ValidationPipeanswers an array or a primitive sent for a validated class with a 400 – 197371c1f3FileTypeValidatormatches a stringfileTypeup to the end of a name (e.g.font/woffno longer acceptsfont/woff2; use a RegExp for that) – 770c6f1a19@SerializeOptions({})on a handler no longer turns off the class schema – d27cb7017fBaseExceptionFilteranswershttp-errorserrors created withexpose: false(the default from 500) with the standard reason phrase instead of their message – 9ed572f853- A
StreamableFileerror still gets a 400, but the body no longer carries the error message – 2f28d91afb - Files uploaded with a request that a pipe rejected are removed from storage – acb98de89e
@nestjs/platform-fastify: a route withfileSize: undefined(ornull) falls back to the plugin's limit; set it toInfinityto keep uploads unlimited – dd549e1a74@nestjs/platform-express: object error bodies are sent asapplication/jsonon routes with a non-JSONContent-Type– 7dc6e349d5ConsoleLoggerin JSON mode cuts a record short past about a million characters – ad4915eaa3- A global enhancer that the injector failed to instantiate now fails the application at startup – ae78524ced
- A request- or transient-scoped
APP_FILTERnow logs a startup warning, as it only applies to exceptions thrown from controllers – df5275c5e1 - Microservices: a pattern key longer than 256 characters matches no handler – accd27e66c
- Kafka: a message may carry up to 10,000 header values (e419ff540b); headers given as a string or array are not sent (312777743f); reply headers are decoded as text (ee94f6aaae)
- gRPC: request streams are paused while their replies wait to be written – 37e5cf7706
- Deprecation: on TCP, Redis, NATS, MQTT and RabbitMQ, an
@EventPattern()handler that replies toClientProxy#send()now logs a deprecation warning. The reply is unchanged; in the next major version event handlers will not reply tosend(), as on Kafka already – ba3668d36b
Middleware exclusions
MiddlewareConsumer.exclude()now compiles excluded routes with the router's case and trailing-slash matching (08d8677c8d). Update@nestjs/coretogether with@nestjs/platform-express/@nestjs/platform-fastify: with an adapter that does not implementgetRouteMatchingOptions(), excluded routes are matched exactly (f5aa875e40), so on a lenient router other spellings of an excluded path run the middleware.- With header, media type or custom versioning,
exclude({ path, method, version })andenableCsrfProtection({ exclude })apply only to requests that ask for one of the excluded versions – 1a7a31fa46 @nestjs/platform-fastify: the request hook used byenableCsrfProtection()anduseSecurityHeaders()now runs before Nest andapp.use()middleware withNestFactory.create()too, including middleware registered before either call, as it already did withTest.createNestApplication()– 8351806290
Bug fixes
platform-fastify- 614d1ac7ea fix(fastify): send the status of an exception whose body is an error (@kamilmysliwiec)
- 8b420f788f fix(fastify): apply middleware to plugins registered before init (@kamilmysliwiec)
- #18175 fix(fastify): keep raw-response cookies in the header helpers (@johnnyhuirilef)
- c215fd9b4f fix(fastify): match middleware paths like a case-insensitive router (@kamilmysliwiec)
- 43d4420205 fix(fastify): pass version extractor errors to the error handler (@kamilmysliwiec)
- 1435ed22f4 fix(fastify): pass middleware rejections to the error handler (@kamilmysliwiec)
- 84c947faf9 fix(fastify): stop reading a streamable file for a head request (@kamilmysliwiec)
- dd549e1a74 fix(fastify): let undefined upload limits fall back to the defaults (@kamilmysliwiec)
- 4735f8d050 fix(fastify): free memory storage chunks once a file is buffered (@kamilmysliwiec)
- 3e3e6eea6f fix(fastify): remove uploads cut off after their last chunk (@kamilmysliwiec)
- c04a9182b9 fix(fastify): set the security headers on router error responses (@kamilmysliwiec)
- a03c7a1db6 fix(fastify): answer request targets that are not a path with 404 (@kamilmysliwiec)
- #18156 fix(fastify): apply route options to all-method routes (@Ahmad-Mosha)
microservices- #18182 fix(microservices): handle malformed kafka reply assigner member metadata (@SssiiiSssii1)
- 83a55aa9dc fix(microservices): leave the init hooks to the hybrid application (@kamilmysliwiec)
- ffd27afe10 fix(microservices): call the init hooks once when init() is called (@kamilmysliwiec)
- #18179 fix(microservices): preserve request order during deferred replay (@Benziza)
- e419ff540b fix(microservices): limit the number of kafka header values (@kamilmysliwiec)
- 312777743f fix(microservices): send no kafka headers given as a string or array (@kamilmysliwiec)
- ee94f6aaae fix(microservices): decode kafka reply headers as text (@kamilmysliwiec)
- 9bdf844fca fix(microservices): limit the size of kafka messages the parser decodes (@kamilmysliwiec)
- 37e5cf7706 fix(microservices): pause grpc request streams while replies wait (@kamilmysliwiec)
- 58262f2542 fix(microservices): end grpc unary subscriptions with the call (@kamilmysliwiec)
- c267a2b3c4 fix(microservices): fail grpc calls whose handler promise rejects (@kamilmysliwiec)
- 85bb407537 fix(microservices): fail grpc response streams that emit null (@kamilmysliwiec)
- 7568c3c34d fix(microservices): send grpc errors that grpc-js can encode (@kamilmysliwiec)
- 932c4359b4 fix(microservices): error grpc duplex calls on upstream error (@kamilmysliwiec)
- 92b009879b fix(microservices): route mqtt messages by the topic they arrived on (@kamilmysliwiec)
- 791bcd335d fix(microservices): validate request ids before echoing them (@kamilmysliwiec)
- 8041a55760 fix(microservices): drain streamed replies in linear time (@kamilmysliwiec)
- accd27e66c fix(microservices): limit the length of pattern keys (@kamilmysliwiec)
- 747c4f25b9 fix(microservices): drop rmq replies that amqp cannot address (@kamilmysliwiec)
- e088f6d8f9 fix(microservices): only emit rmq replies that a request waits for (@kamilmysliwiec)
- b2e8367f36 fix(microservices): reject mqtt topics longer than 65535 bytes (@kamilmysliwiec)
- 47eb92b6b5 fix(microservices): count mqtt requests that wait for the subscription (@kamilmysliwiec)
- d79db40cee fix(microservices): drop idle reply channels from subscription counts (@kamilmysliwiec)
- ce7e6a6c36 fix(microservices): use unguessable request ids and nats reply inboxes (@kamilmysliwiec)
- ede1693fc4 fix(microservices): emit plain rpc filter results once on stream errors (@kamilmysliwiec)
- 2ab152ee4a fix(microservices): honor falsy results of rpc exception filters (@kamilmysliwiec)
- a63cea600a fix(microservices): keep reconnecting the mqtt server after a refusal (@kamilmysliwiec)
- c1391c6b50 fix(microservices): flatten async rpc filter results on stream errors (@kamilmysliwiec)
- 99ee9f88c4 fix(microservices): stop tcp observable responses when the peer leaves (@kamilmysliwiec)
- 7dd0c49ade fix(microservices): reply to a request only from its message handler (@kamilmysliwiec)
- 583d6077ad fix(microservices): drop tcp peers that stop reading their responses (@kamilmysliwiec)
- e0cdd0e01d fix(microservices): use the right filters for inherited scoped handlers (@kamilmysliwiec)
- 29d59c75e5 fix(microservices): keep sibling event handlers running on error (@kamilmysliwiec)
- a8480ec7be fix(microservices): drop the mqtt client when a reconnect is refused (@kamilmysliwiec)
- 05b4dfd1ed fix(microservices): reject tcp data too long to be a content length (@kamilmysliwiec)
- f3bce4ca90 fix(microservices): consume again after the rmq consumer is cancelled (@kamilmysliwiec)
- e7e7ea7525 fix(microservices): close tls connections still in their handshake (@kamilmysliwiec)
- #18165 fix(microservices): close rmq server connection when channel close fails (@kamilmysliwiec)
- #18159 fix(microservices): run other event handlers when a scoped one fails (@OmBhandwaldar)
- #18162 fix(microservices): keep reading tcp replies during client backpressure (@maxymlyskov)
- #18161 fix(microservices): close the rmq channel before the connection (@maxymlyskov)
- #18125 fix(microservices): ignore a redis server's own replies under wildcards (@maxymlyskov)
- #18127 fix(microservices): match empty mqtt topic levels (@ys0v9)
core- 85d0a0be92 fix(core): run interceptor, pipe and filter classes without a name (@kamilmysliwiec)
- #18186 fix(core): detect cycles in request-scoped forward references (@DevAhmadAlkhuja)
- #18180 fix(core): give a module that extends another module its own id (@maxymlyskov)
- bafce3bae8 fix(core): answer http requests an rpc exception filter leaves (@kamilmysliwiec)
- 8f9fbfd76f fix(core): settle async param decorator values before pipes run (@kamilmysliwiec)
- fec478e96b fix(core): subscribe to guard observables from other copies of rxjs (@kamilmysliwiec)
- 034ef09b0c fix(core): run guards bound as classes without a name (@kamilmysliwiec)
- d1a5e0dd31 fix(core): find the module of a host registered under another token (@kamilmysliwiec)
- c8eaf8a4f5 fix(core): run middleware on a controller root excluded by a wildcard (@kamilmysliwiec)
- 7b01d0e7a9 fix(core): stop wildcard exclusions from covering their parent route (@kamilmysliwiec)
- fffdaf9b22 fix(core): mount middleware paths on routes excluded from the prefix (@kamilmysliwiec)
- 77d28b6336 fix(core): drop an overlapped middleware route only when it is covered (@kamilmysliwiec)
- b24d469d60 fix(core): mount unversioned middleware paths under the default version (@kamilmysliwiec)
- 98e3ba4ef2 fix(core): map controller middleware under every module declaring it (@kamilmysliwiec)
- bd19a1fb79 fix(core): mount transient-scoped middleware instead of skipping it (@kamilmysliwiec)
- 9028243aea fix(core): never exclude request targets with "#" or in absolute form (@kamilmysliwiec)
- 97ab04494c fix(core): hide internal error messages from sse error events (@kamilmysliwiec)
- f28f00cffa fix(core): drop sse clients that stop reading their events (@kamilmysliwiec)
- 31d077a7b2 fix(core): hand sse header errors to the exception filters (@kamilmysliwiec)
- a251be75ec fix(core): leave early sse errors to the exception filters (@kamilmysliwiec)
- d73acb5142 fix(core): trim only spaces and tabs around cookie names and values (@kamilmysliwiec)
- 52509a55a9 fix(core): wait for the redirect reply before settling the route (@kamilmysliwiec)
- 609e7cee9e fix(core): stop reusing durable instances holding a failed placeholder (@kamilmysliwiec)
- a4c83f062a fix(core): run transient global enhancers on static entry providers (@kamilmysliwiec)
- ae78524ced fix(core): fail at startup when a global enhancer is not instantiated (@kamilmysliwiec)
- d6787cd765 fix(core): await deferred loads of forward-referenced providers (@kamilmysliwiec)
- 9ee9bdc7fc fix(core): inject every property of overlapping first resolutions (@kamilmysliwiec)
- 71de6123da fix(core): keep the root inquirer of transient providers per resolution (@kamilmysliwiec)
- 15a73755c0 fix(core): apply the enhancers of class providers under any token (@kamilmysliwiec)
- 93de671c67 fix(core): recompute scope flags cached inside a circular dependency (@kamilmysliwiec)
- 7ea6ff0665 fix(core): run enhancers that are request-scoped through dependencies (@kamilmysliwiec)
- cb1c0e8242 fix(core): destroy a
StreamableFilethat is not sent (@kamilmysliwiec) - 0b20c89d47 fix(core): destroy a
StreamableFiledropped by a timed-out handler (@kamilmysliwiec) - df5275c5e1 fix(core): warn that scoped global filters miss non-controller errors (@kamilmysliwiec)
- 9ed572f853 fix(core): do not send the message of an unexposed http error (@kamilmysliwiec)
- 0692996cb5 fix(core): answer host mismatches on fastify with 404 (@kamilmysliwiec)
- cbac8c1f5a fix(core): use the right filters for inherited request-scoped middleware (@kamilmysliwiec)
- 1828c8d638 fix(core): keep exact routes ahead of optional groups by specificity (@kamilmysliwiec)
- 2a818a592c fix(core): end sse responses to head requests once headers are sent (@kamilmysliwiec)
- 816bf48460 fix(core): use the right filters for inherited request-scoped routes (@kamilmysliwiec)
- 8ef358804c fix(core): honor falsy results of filters in external contexts (@kamilmysliwiec)
- #18154 fix(core): treat fastify validation errors as http errors (@OmBhandwaldar)
- #18142 fix(core): reject create() when a dependency is request-scoped (@maxymlyskov)
- #18137 fix(core): release the throwaway wrapper of each create() call (@maxymlyskov)
- #18121 fix(core): keep route options when the route triggered hook is set (@OmBhandwaldar)
common- 770c6f1a19 fix(common): match a file type string up to the end of a name (@kamilmysliwiec)
- 8c5a59bf63 fix(common): stop exposing the validated object on validation errors (@kamilmysliwiec)
- 086c1c514f fix(common): limit the length of validation error messages by default (@kamilmysliwiec)
- e77ceba917 fix(common): stop copying nested validation errors for each level (@kamilmysliwiec)
- 197371c1f3 fix(common): reject arrays and primitives for validated classes (@kamilmysliwiec)
- b34a359be8 fix(common): validate parsed array items one at a time (@kamilmysliwiec)
- 2f28d91afb fix(common): keep
StreamableFileerror messages out of responses (@kamilmysliwiec) - 21a0462ffd fix(common): handle
StreamableFileerrors raised before the reply (@kamilmysliwiec) - d27cb7017f fix(common): keep the class schema when a handler sets serialize options (@kamilmysliwiec)
- 06853bc555 fix(common): keep the loaded transformer while serializers are created (@kamilmysliwiec)
- 67761deac7 fix(common): strip a falsy constructor key from request data (@kamilmysliwiec)
- ad4915eaa3 fix(common): cut json log records short past a million characters (@kamilmysliwiec)
- aa1e402ecc fix(common): traverse a shared object once in the logger redactor (@kamilmysliwiec)
- 7aca0438a9 fix(common): keep custom decorator options followed by a pipe (@kamilmysliwiec)
- 931007e504 fix(common): copy array and object defaults in
DefaultValuePipe(@kamilmysliwiec) - fa0ff8b25a fix(common): skip array holes when stripping prototype keys (@kamilmysliwiec)
- #18157 fix(common): avoid mutating input arrays during validation (@dcavalcante)
- #18146 fix(common): call
stringifyReplacerwith the logger asthis(@Chaoqi31) - #18145 fix(common): detect stacks whose error message spans several lines (@Chaoqi31)
- #18144 fix(common): parse
error()calls with a lone or an undefined stack (@Chaoqi31)
platform-express,platform-fastify- #18178 fix(express,fastify): parse quoted media type version parameters (@li-jia-nan)
- 1933cc9edd fix(express,fastify): handle a
StreamableFilethat cannot be streamed (@kamilmysliwiec) - e075cda3c3 fix(express,fastify): let a route's dest replace the module's storage (@kamilmysliwiec)
- 94fcc93770 fix(express,fastify): limit field nesting and array indexes by default (@kamilmysliwiec)
testing- #18170 fix(testing): share one auto-mock between providers of the same token (@jayhemnani9910)
- #18158 fix(testing): resolve auto-mocked dependencies of transient providers (@jayhemnani9910)
core,microservices- 9b77f565bd fix(core,microservices): let only the hybrid application bind gateways (@kamilmysliwiec)
websockets- 8ec95a8de7 fix(websockets): await deferred loads of a gateway's scoped enhancers (@kamilmysliwiec)
- ebc545cac9 fix(websockets): create the filters of a gateway that failed to resolve (@kamilmysliwiec)
- 6cef28fee3 fix(websockets): resolve hook error filters in the connection's context (@kamilmysliwiec)
- d4aacbc8e6 fix(websockets): use the right filters for inherited gateway handlers (@kamilmysliwiec)
- 5c055fbf92 fix(websockets): log and reply when the error cause cannot be sent (@kamilmysliwiec)
core,websockets- a1908877ae fix(core,websockets): run transient enhancers bound to static gateways (@kamilmysliwiec)
- #18143 fix(core): key the handler metadata cache by class, not class name (@maxymlyskov)
common,core- 1a7a31fa46 fix(core,common): exclude a version only for requests that ask for it (@kamilmysliwiec)
- 2f05ad954e fix(core): make the sse pending data limit configurable (@kamilmysliwiec)
- f5aa875e40 fix(core): match excluded routes exactly when the router is unknown (@kamilmysliwiec)
core,platform-express- fb8c2cac7f fix(core): mount wildcard middleware on every path when "/" is excluded (@kamilmysliwiec)
platform-express- b75244ffd2 fix(express): run wildcard middleware on "/api/" for a named wildcard (@kamilmysliwiec)
- 8b8e8396f7 fix(express): stop reading a streamable file for a head request (@kamilmysliwiec)
- 7dc6e349d5 fix(express): send object error bodies with a json content type (@kamilmysliwiec)
platform-ws,websockets- db4e586c53 fix(ws): stop reading from a client that does not read its replies (@kamilmysliwiec)
- 146c5c41b2 fix(ws): drop messages from a client the server is closing (@kamilmysliwiec)
platform-socket.io,platform-ws,websockets- 0bd0810ed7 fix(websockets): bound how many messages of a client are handled at once (@kamilmysliwiec)
core,microservices,websockets- 4048e37790 fix(core,microservices,websockets): ignore inherited keys of non-objects (@kamilmysliwiec)
- e31d925a59 fix(core): read class-level enhancers from the registered class (@kamilmysliwiec)
platform-ws- b00c1ed9ab fix(ws): listen on the host of a gateway with its own port and a path (@kamilmysliwiec)
- 300b95c3d6 fix(ws): answer non-upgrade requests on a gateway's own port with 426 (@kamilmysliwiec)
- 59f772babf fix(ws): close the socket of an upgrade request it cannot parse (@kamilmysliwiec)
core,platform-express,platform-fastify- acb98de89e fix(core,express,fastify): remove uploads of requests a pipe rejected (@kamilmysliwiec)
core,testing- #18166 fix(core): fail at bootstrap on missing deps of scoped providers (@kamilmysliwiec)
- #18164 fix(testing): mock dependencies of request-scoped providers (@johnnyhuirilef)
common,platform-fastify- 8351806290 fix(fastify): run the security request hook ahead of middie (@kamilmysliwiec)
common,core,platform-express,platform-fastify- 08d8677c8d fix(core,express,fastify): match excluded routes like the router does (@kamilmysliwiec)
common,core,microservices,platform-express,platform-fastify,platform-socket.io,platform-ws,testing,websockets
Enhancements
microservices- ba3668d36b feat(microservices): deprecate event handlers replying to send() (@kamilmysliwiec)
core- #18147 perf(core): resolve route params without a promise when no pipe runs (@thekhegay)
- #18136 perf(core): avoid AsyncResource.bind() per request in the interceptor chain (@thekhegay)
Docs
- #18185 docs(sample): document file upload validation examples (@li-jia-nan)
microservices- e9ebd67c2b docs(microservices): document kafka messages without reply headers (@kamilmysliwiec)
Dependencies
platform-fastify- #18153 fix(deps): update dependency light-my-request to v6.8.0 (@renovate[bot])
- #18152 fix(deps): update dependency find-my-way to v9.10.0 (@renovate[bot])
- #18131 fix(deps): update dependency fastify to v5.12.7 (@renovate[bot])
platform-express- #18150 fix(deps): update dependency express to v5.3.0 (@renovate[bot])
Committers: 15
- Ahmed Gamal (@Ahmad-Mosha)
- Chaoqi (@Chaoqi31)
- Daniel Cavalcante (@dcavalcante)
- Jay Hemnani (@jayhemnani9910)
- Johnny J. Huirilef Millán (@johnnyhuirilef)
- Kamil Mysliwiec (@kamilmysliwiec)
- Maksym Lyskov (@maxymlyskov)
- Minijus L (@minijus)
- Mohamed A. Abdel Fattah (@SssiiiSssii1)
- Om Bhandwaldar (@OmBhandwaldar)
- Roman Khegay (@thekhegay)
- Sua Choi (@ys0v9)
- @Benziza
- @DevAhmadAlkhuja
- lijianan (@li-jia-nan)