v12.5.0 (2026-11-12)
Notable changes
New options
WsAdaptertakesmaxPayload, the largest message a client may send (1 MB by default, was 100 MB; a gateway's ownmaxPayloadtakes precedence,0lifts the limit); a larger message closes the connection with code 1009 – 109e52cd9bIoAdaptertakesmaxWaitingMessages, the number of a client's messages of one event that may wait beyond those being handled (10,000 by default;Infinitylifts it) – c98b5f782e- TCP server:
maxConcurrentMessages(1000 per connection by default;0lifts it) – 42c619cd69 - gRPC server:
maxPendingResponses(1000 by default;0disables), after which a streaming call whose client leaves its responses unread fails withRESOURCE_EXHAUSTED– ce6d44d858 - Redis server:
maxWildcardChannelLength(1024 characters by default;0disables) for requests matched through a wildcard subscription – 074dcf7c60 - RabbitMQ:
maxMessageSize(16 MiB by default) for messages and replies decoded as JSON – da6b3fc5bc @nestjs/platform-fastify: multipartlimits.jsonFieldsSize(1 MiB by default) for the fields of a request sent asapplication/json– 958316696f
New defaults and behaviour changes
- TCP:
maxBufferSizedefaults to 16 Mi characters (was 128 Mi), in both directions – 55da0b0d33 – and now applies to each packet rather than to everything received in one read, so a burst of small packets no longer closes the connection (#18502) – ce285e6ad3 - TCP server: an empty or unset
hostnow listens on localhost; sethost: '0.0.0.0'(or'::') to listen on every interface – 4196d3655d @nestjs/platform-express,@nestjs/platform-node: multipart requests default to at most 1000 parts, which also caps afields,filesormaxCountabove 1000 unlesslimits.partsis raised – b2bbc17122- An upload option a route sets to
undefinedornullnow keeps the module's value; useInfinityto lift a limit – 7bc8d9121e - A limit option given as
NaN(e.g.Number(process.env.UNSET)) now gets its default instead of turning the limit off, for TCP, Kafka,WsAdapter,IoAdapter, the validation pipes and@Sse()– 8209d1c8be, f956177a0e, 5b58a6e89f ClassSerializerInterceptorandStandardSchemaSerializerInterceptorserialize each object a streamed HTTP response yields, so@Exclude(), groups and schemas apply to every line of NDJSON – 8217f2b3b8@Sse(): while Node.js has paused the socket of a client, a:comment is written every 5 s, so that a client that left is noticed – cd963b19bd@nestjs/platform-express,@nestjs/platform-node: aSyntaxErrororURIErrorwithout a 400 status (e.g. thrown by a middleware passed toapp.use()) is answered with a logged 500 rather than a 400 carrying its message – 8d74ddcd3a@nestjs/platform-node: when the matched route would leave a route parameter empty, the request is a 404 – 56c06f48c3- Middleware given to
forRoutes()is mounted where the router serves the routes it covers, including routes excluded from the global prefix – 521cdea80f - Parameter pipes of controllers built with mixins or wrapped by a class decorator that returns a Proxy now run – 7c5792d969
- The
excludepredicate ofenableCsrfProtection()excludes a request only when it returnstrue– 608fcec0a9 - Gateways on their own port drop clients that connect before
onApplicationBootstrap()has finished; socket.io clients reconnect – 7d705cc835 - In a standalone microservice, a gateway without a port no longer opens a server on a random port; it gets a server that does not listen – 7359d3b06a
- An
@Optional()dependency that exists but fails to build at request time now fails its consumer – 0c360708b5 - Transient providers with durable dependencies are built per request – 822d93ffd1
moduleRef.create()rejects a request-scoped property dependency, as it does for constructor parameters – 6c5fed8b72
New startup errors and warnings
- A guard, interceptor or pipe that can't run (e.g. an abstract class used as a token, or a class given as the
useValueofAPP_GUARD) fails the application at startup; an exception filter that can't run logs a warning – 7a81aed500, 407518855f - An invalid
forRoutes()orexclude()entry fails the application at startup – 1afb768959 - A gateway that joins a shared server with a
verifyClientorallowRequestthe server won't run, or gateways on one port that set different hosts, stop the application at startup – 32875410dc, fd0155fba0 @nestjs/platform-fastify:@All('x')declared above@Search('x')or a WebDAV method on the same path fails at startup, as the reverse order already did;@All()routes now also answer these methods – a1695d18ea- Warnings for exception filter classes bound to a middleware, which don't apply – 3113f03f1e – and for a
ValidationPipethat gets no parameter types – f433a1f752
Microservices
- gRPC: an
Errorwrapped in anRpcExceptionis logged and answered as "Internal server error"; its numeric code is still used as the status – 2038bff425 - A filter that throws on a response stream is logged and answered as "Internal server error" – 515f99cfb6
- Kafka: events can no longer ask for a reply through reply headers, and replies no longer carry them – d1473338c3; an object with a
keyorvalueand other properties is sent as the payload – 73373dc911; a request whose reply topic is one the server handles itself is dropped – 809029b74b - RabbitMQ wildcards: a message whose pattern names a different handler than its routing key is not handled – ef8f92c5d0
- Patterns with a string value over 4096 characters or more than 100 keys get a marker route – ed8ca5cded; multi-key patterns with a non-ASCII key may get a new route, so clients and servers of such patterns should be on the same version – 015456cc2f
@nestjs/core and the platform packages should be updated together, as the adapters pass new route matching options to core.
Bug fixes
platform-fastify- fecdd4f9ef fix(fastify): fail an object-mode file stream on a non-bytes chunk (@kamilmysliwiec)
- 5f08564c8b fix(fastify): release file streams of pipelined requests on close (@kamilmysliwiec)
- 9934bcffc6 fix(fastify): handle a failed file stream on a raw response (@kamilmysliwiec)
- 3276fac6a4 fix(fastify): match routes whose parameter names the router misreads (@kamilmysliwiec)
- 890a77a6e2 fix(fastify): merge small file chunks in memory storage as they arrive (@kamilmysliwiec)
- a1695d18ea fix(fastify): serve the webdav and search methods with @ALL() routes (@kamilmysliwiec)
- 9cac4da423 fix(fastify): treat an empty repeated route parameter as a route miss (@kamilmysliwiec)
- f7dd51ed05 fix(fastify): handle async body parsers and app.use() middleware errors (@kamilmysliwiec)
- ed4c86da44 fix(fastify): lower-case middleware paths like a case-insensitive router (@kamilmysliwiec)
- 0904f6892c fix(fastify): handle "proto" in urlencoded bodies like json ones (@kamilmysliwiec)
- b1ee5387b0 fix(fastify): track plugin contexts when the app registers middie (@kamilmysliwiec)
- b37cc34e85 fix(fastify): remove stored uploads when a client leaves a stalled form (@kamilmysliwiec)
- 0bf9cc534b fix(fastify): remove the partial file of a cut-off multipart form (@kamilmysliwiec)
- 4367d446b2 fix(fastify): fail the file stream of a discarded upload (@kamilmysliwiec)
- 958316696f fix(fastify): bound the size of multipart fields parsed as json (@kamilmysliwiec)
microservices- 9aa196d14c fix(microservices): skip scoped global filters not created for a context (@kamilmysliwiec)
- 972a59283a fix(microservices): log handler failures of grpc stream calls (@kamilmysliwiec)
- ce061111ce fix(microservices): wait for every pipe of a message before failing it (@kamilmysliwiec)
- 2038bff425 fix(microservices): handle errors in rpc exceptions as unknown in grpc (@kamilmysliwiec)
- 015456cc2f fix(microservices): sort non-ascii pattern keys without localecompare (@kamilmysliwiec)
- 222e8efffd fix(microservices): run scoped filters for controller resolution errors (@kamilmysliwiec)
- 078945a877 fix(microservices): observe the promises of joined event handlers (@kamilmysliwiec)
- 515f99cfb6 fix(microservices): use the default filter when an rpc filter fails (@kamilmysliwiec)
- ed8ca5cded fix(microservices): apply the pattern limits before serializing it (@kamilmysliwiec)
- 42c619cd69 fix(microservices): bound how many messages of a tcp peer are handled (@kamilmysliwiec)
- 7b4fa32920 fix(microservices): end streams of tcp messages emitted without an id (@kamilmysliwiec)
- 4196d3655d fix(microservices): listen on localhost for an empty tcp host option (@kamilmysliwiec)
- b93dc04b2a fix(microservices): flatten the tcp packet buffer after many small reads (@kamilmysliwiec)
- ce285e6ad3 fix(microservices): apply the tcp maxbuffersize to each packet (@kamilmysliwiec)
- 8209d1c8be fix(microservices): use the default tcp and kafka limits for nan (@kamilmysliwiec)
- 55da0b0d33 fix(microservices): lower the default tcp maxbuffersize to 16 mi (@kamilmysliwiec)
- 8f9764a369 fix(microservices): skip nest replies arriving on nats handler subjects (@kamilmysliwiec)
- 074dcf7c60 fix(microservices): limit the redis channels wildcard requests reply on (@kamilmysliwiec)
- 76064f3550 fix(microservices): reject mqtt topic names with wildcards in clientmqtt (@kamilmysliwiec)
- 1634286a24 fix(microservices): match mqtt wildcard filters against the sent topic (@kamilmysliwiec)
- cc2157b828 fix(microservices): count redis requests that wait for the subscription (@kamilmysliwiec)
- 5c379b378c fix(microservices): print the id of an unmatched redis reply safely (@kamilmysliwiec)
- 616ca2c9bf fix(microservices): fail grpc client calls whose requests emit null (@kamilmysliwiec)
- ce6d44d858 fix(microservices): fail grpc streams whose client leaves replies unread (@kamilmysliwiec)
- 22efb87c56 fix(microservices): send grpc error messages that are not strings (@kamilmysliwiec)
- 02df2ab9ed fix(microservices): end grpc client stream calls cancelled early (@kamilmysliwiec)
- 73373dc911 fix(microservices): send objects with other fields as kafka payloads (@kamilmysliwiec)
- ef8f92c5d0 fix(microservices): check the routing key of rmq wildcard messages (@kamilmysliwiec)
- 809029b74b fix(microservices): refuse kafka reply topics the server handles itself (@kamilmysliwiec)
- d1473338c3 fix(microservices): send kafka events and replies without reply headers (@kamilmysliwiec)
- 7032924995 fix(microservices): log kafka entries that json cannot serialize (@kamilmysliwiec)
- 50c429c9d3 fix(microservices): keep the kafka consumer running after type errors (@kamilmysliwiec)
- fe925e3a36 fix(microservices): stop kafka servers from keeping streamed replies (@kamilmysliwiec)
- 54025a63b7 fix(microservices): skip rmq wildcard matching for over-long patterns (@kamilmysliwiec)
- f4a2648ec6 fix(microservices): reject rmq short strings longer than 255 bytes (@kamilmysliwiec)
- ada06f1e50 fix(microservices): validate kafka and rmq request ids before echoing (@kamilmysliwiec)
- da6b3fc5bc fix(microservices): limit the size of rmq messages decoded as json (@kamilmysliwiec)
- #18500 fix(microservices): chain kafka event handlers with equal regex patterns (@thekhegay)
- #18499 fix(microservices): handle a cancelled rmq reply consumer in client (@thekhegay)
- #18491 fix(microservices): fail pending rmq requests when the connection drops (@jaeminbird)
platform-express- d2319b8c4a fix(express): remove rejected uploads of pipelined requests on close (@kamilmysliwiec)
- d55889431c fix(express): fail an object-mode file stream on a non-bytes chunk (@kamilmysliwiec)
- 37c9852b61 fix(express): release file streams of pipelined requests on close (@kamilmysliwiec)
- af4b59bbf1 fix(express): answer a failed file stream with plain text (@kamilmysliwiec)
- b6849654de fix(express): map only client syntax and uri errors to 400 (@kamilmysliwiec)
- 7a038c32be fix(express): render a copy of the value a handler returns (@kamilmysliwiec)
platform-node- 8d74ddcd3a fix(node): map only client syntax and uri errors to 400 (@kamilmysliwiec)
- 81f9d0c1f7 fix(node): release file streams of pipelined requests on close (@kamilmysliwiec)
- a0a64f504e fix(node): fail an object-mode file stream on a non-bytes chunk (@kamilmysliwiec)
- 832c4eeb7f fix(node): catch what the error handler of a file stream throws (@kamilmysliwiec)
- 56c06f48c3 fix(node): treat an empty parameter of the matched route as a miss (@kamilmysliwiec)
- ba24b20199 fix(node): match "//" as the pattern of a root optional group route does (@kamilmysliwiec)
- 31083b74c5 fix(node): merge small body chunks as they arrive (@kamilmysliwiec)
- 564386c700 fix(node): pass errors of the send file callback to the error handlers (@kamilmysliwiec)
- f2df95c251 fix(node): validate the headers option of a sent file up front (@kamilmysliwiec)
- 5fbead36d0 fix(node): leave the router on next('router') as express does (@kamilmysliwiec)
- 8d9bcd79ed fix(node): reject multipart field names that set prototype keys (@kamilmysliwiec)
common,core- 5b58a6e89f fix(common,core): use the default for pipe and sse limits given as nan (@kamilmysliwiec)
- 608fcec0a9 fix(core,common): exclude requests only when the predicate returns true (@kamilmysliwiec)
- c88524238b fix(core,common): read the catch types of a filter from its prototype (@kamilmysliwiec)
- 732a944d03 fix(common,core): send the status text in sse errors that wrap an error (@kamilmysliwiec)
- 2d3f7d7d44 fix(common,core): count sse events without data toward the pending limit (@kamilmysliwiec)
platform-socket.io,platform-ws- f956177a0e fix(ws,socket.io): use the default for adapter limits given as nan (@kamilmysliwiec)
core- 407518855f fix(core): warn about an exception filter that can't run (@kamilmysliwiec)
- 7a81aed500 fix(core): throw for a guard, interceptor or pipe that can't run (@kamilmysliwiec)
- 2dffe900d0 fix(core): run the container instance of a class-bound enhancer (@kamilmysliwiec)
- 1704079dd2 fix(core): use the enhancers of the module that holds the host (@kamilmysliwiec)
- d83c04660d fix(core): mount middleware on a route path that really ends in "$" (@kamilmysliwiec)
- f68f411337 fix(core): mount a controller root route without the slash after a tail (@kamilmysliwiec)
- 334ee38d97 fix(core): resolve a forward reference to a module only once (@kamilmysliwiec)
- f61a8aae35 fix(core): mount module middleware in order when configure() awaits (@kamilmysliwiec)
- 1afb768959 fix(core): reject a middleware target that is not a controller or route (@kamilmysliwiec)
- 3113f03f1e fix(core): warn that filter classes bound to a middleware do not apply (@kamilmysliwiec)
- 24b63cf391 fix(core): keep the filters of a middleware's use() with exclude() (@kamilmysliwiec)
- 000bde2261 fix(core): test each versioned path against the prefix exclusions alone (@kamilmysliwiec)
- 521cdea80f fix(core): mount middleware where the router serves the covered routes (@kamilmysliwiec)
- 39de21dddd fix(core): compare a prefix exclusion with a trailing slash as served (@kamilmysliwiec)
- e723fc84d0 fix(core): run the middleware for a path with a line terminator (@kamilmysliwiec)
- d74ba14f0b fix(core): keep a controller root route next to an optional-tail route (@kamilmysliwiec)
- 81ee78ef47 fix(core): inject the provider an alias stands for (@kamilmysliwiec)
- 3c6a260864 fix(core): inject the strategy payload into durable providers as request (@kamilmysliwiec)
- 822d93ffd1 fix(core): keep transient instances out of durable sub-trees (@kamilmysliwiec)
- 6ceb474d14 fix(core): release removed wrappers from the providers they depended on (@kamilmysliwiec)
- 0c360708b5 fix(core): fail the consumer when an optional dependency fails to load (@kamilmysliwiec)
- 93ce700f3d fix(core): build a lazy module once when loads overlap (@kamilmysliwiec)
- bcec39b079 fix(core): give unserializable dynamic modules their own deep-hash ids (@kamilmysliwiec)
- 6c5fed8b72 fix(core): reject create() when a property dependency is request-scoped (@kamilmysliwiec)
- cfd91d1ef0 fix(core): keep create() working after many calls in snapshot mode (@kamilmysliwiec)
- fe66fc7af0 fix(core): stop reloading durable instances marked by a failed load (@kamilmysliwiec)
- 179bed92c8 fix(core): skip exception filters that were not created for a request (@kamilmysliwiec)
- 666371c119 fix(core): answer http errors that graphql or async rpc filters leave (@kamilmysliwiec)
- 740b26821d fix(core): keep host params matched next to an optional group (@kamilmysliwiec)
- cd963b19bd fix(core): notice an sse client that left while its socket is paused (@kamilmysliwiec)
- 2192b74f21 fix(core): write the waiting events of an sse client in linear time (@kamilmysliwiec)
- 5dee8a4cce fix(core): catch what the teardown of an sse producer throws (@kamilmysliwiec)
- fc2e03564f fix(core): send what the interceptors return for a streaming handler (@kamilmysliwiec)
- 43ac5f0abe fix(core): share one close listener among the requests of a connection (@kamilmysliwiec)
- 80959ee2f2 fix(core): read a streamed body in the async context of its request (@kamilmysliwiec)
- 4fbd7ae9cd fix(core): listen for the error of every stream the router holds (@kamilmysliwiec)
common,core,microservices,websockets- 7d705cc835 fix(core,microservices,websockets): drop gateway clients during startup (@kamilmysliwiec)
core,microservices,websockets- f433a1f752 fix(core): warn when a validation pipe gets no parameter types (@kamilmysliwiec)
- 7c5792d969 fix(core,websockets): read parameter metadata from the declaring class (@kamilmysliwiec)
platform-socket.io,platform-ws,websockets- 7359d3b06a fix(websockets,ws,socket.io): open no port for a gateway without one (@kamilmysliwiec)
- c98b5f782e fix(socket.io): cap how many messages of a client wait for their turn (@kamilmysliwiec)
- 55509f683e fix(websockets,ws,socket.io): free a client's last handled message (@kamilmysliwiec)
websockets- 32875410dc fix(websockets): refuse a gateway whose connection check would not run (@kamilmysliwiec)
- d6c3e2fa8b fix(websockets): share streams of gateways on "/" and on no namespace (@kamilmysliwiec)
- bd01f0f216 fix(websockets): wait for every pipe of a message before failing it (@kamilmysliwiec)
- ed988e6061 fix(websockets): run a scoped gateway's disconnect hook after connect (@kamilmysliwiec)
- 8619bc84db fix(websockets): log an error of a connection hook's exception filter (@kamilmysliwiec)
- c99f3318c4 fix(websockets): keep the options of a gateway whose port is not set (@kamilmysliwiec)
- 6ff160ca75 fix(websockets): share one host between gateways of a namespace (@kamilmysliwiec)
- a97e5bf6e1 fix(websockets): connect gateways in the order they are declared in (@kamilmysliwiec)
platform-socket.io,websockets- 5ddb0943f3 fix(websockets,socket.io): stop echoing binary data in error replies (@kamilmysliwiec)
platform-ws,websockets- ce948b18d4 fix(websockets): count a message as handled until its filter is done (@kamilmysliwiec)
platform-ws- fd0155fba0 fix(ws): refuse gateways on one port that set different hosts (@kamilmysliwiec)
- d2cc65fda7 fix(ws): refuse a client whose upgrade check throws (@kamilmysliwiec)
- f6490a7d6e fix(ws): notice a paused client that has left (@kamilmysliwiec)
- aae7cb067c fix(ws): keep a client paused while any gateway on it is backlogged (@kamilmysliwiec)
- 109e52cd9b fix(ws): limit the size of the messages a client may send (@kamilmysliwiec)
- #18501 fix(ws): leave upgrade requests for other paths to other listeners (@mtnaskari)
common,core,platform-fastify- c1de2876b7 fix(core,fastify): match the text after an excluded param as written (@kamilmysliwiec)
- 4ab54e0740 fix(core,fastify): end the excluded path at ";" like the fastify router (@kamilmysliwiec)
- f218bf25b5 fix(core,fastify): exclude "/x/" only when no other route may serve it (@kamilmysliwiec)
common,core,platform-fastify,platform-node- a103e802cb fix(core,fastify,node): match excluded params up to the router's limit (@kamilmysliwiec)
platform-fastify,platform-node- f5155c7db9 fix(fastify,node): match middleware in the forms the router decodes (@kamilmysliwiec)
common- abc5ab727b fix(common): keep the scope a class declares when passed to mixin() (@kamilmysliwiec)
- 8217f2b3b8 fix(common): serialize the objects a streamed http response yields (@kamilmysliwiec)
- 0a15f172d3 fix(common): serialize the values of a stream in linear time (@kamilmysliwiec)
- 762d97afc2 fix(common): close the gaps of sparse arrays the pipes validate (@kamilmysliwiec)
- 738f57be2c fix(common): validate the files of parse file pipe one at a time (@kamilmysliwiec)
- ff36f9b71a fix(common): validate a stand-in for a buffer sent as the whole value (@kamilmysliwiec)
- bf2669e044 fix(common): reject a buffer held by a nested validated property (@kamilmysliwiec)
- ecc95fb064 fix(common): reject a buffer sent in place of a validated class (@kamilmysliwiec)
- f5596e335f fix(common): drop the value of validation errors that have children (@kamilmysliwiec)
- 0e49a3ca8a fix(common): rethrow non-validation errors in the parse array pipe (@kamilmysliwiec)
- f4cb86b4d3 fix(common): limit the length of standard schema error messages (@kamilmysliwiec)
- 66524e9e61 fix(common): limit the error messages of parsed array items in total (@kamilmysliwiec)
- fe2b02d2de fix(common): check the json log record cap before converting values (@kamilmysliwiec)
- 2743f4d750 fix(common): count empty strings toward the json log record cap (@kamilmysliwiec)
- 8e2edd4d31 fix(common): keep logged key names out of the redactor cache keys (@kamilmysliwiec)
- #18480 fix(common): let a null depth print every level in the console logger (@gjija)
platform-express,platform-fastify,platform-node- 0e29eace9d fix(express,fastify,node): close the array gaps of multipart bodies (@kamilmysliwiec)
- 30c76735df fix(express,fastify,node): cut off an upload once the response is sent (@kamilmysliwiec)
- 70f50b0316 fix(express,fastify,node): fail the request when an upload filter throws (@kamilmysliwiec)
- 7bc8d9121e fix(express,fastify,node): keep module upload options a route leaves out (@kamilmysliwiec)
platform-express,platform-node- b2bbc17122 fix(express,node): default the multipart parts limit to 1000 (@kamilmysliwiec)
- #18488 fix(sample): await
resolvesassertions in 05-sql-typeorm unit tests (@ThiagoACNascimento) microservices,websockets- #18487 fix(microservices,websockets): scope parameter pipes to each context (@beyondwin)
Docs
microservices
Committers: 7
- G (@gjija)
- Jae Birdsall (@jaeminbird)
- Kamil Mysliwiec (@kamilmysliwiec)
- Matin Askari | متین عسکری (@mtnaskari)
- Roman Khegay (@thekhegay)
- Thiago Nascimento (@ThiagoACNascimento)
- WooSeung Kim (@beyondwin)