Changelog
Refer to the 2.12 Upgrade Guide for backwards compatibility notes with 2.11.x.
Go Version
- 1.25.8
Dependencies
- github.com/nats-io/nkeys v0.4.15 (#7797)
- github.com/klauspost/compress v1.18.4 (#7812)
- golang.org/x/sys v0.42.0 (#7923)
- github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op (#7835)
- golang.org/x/crypto v0.48.0 (#7874)
- github.com/nats-io/nats.go v1.49.0 (#7835)
- golang.org/x/time v0.15.0 (#7923)
CVEs
- Fixes CVE-2026-29785 (affects systems with leafnode compression enabled)
- Fixes CVE-2026-27889 (affects systems with WebSockets enabled)
Added
JetStream
- The stream snapshot/backup endpoint now accepts the
window_sizeparameter, to allow improving flow control over slow or unreliable connections (#7839)
Improved
General
max_connsin the server configuration can now be configured to0(zero) to reject all incoming client connections (#7877)
JetStream
- "Catchup for stream" log lines are now more consistent (#7784)
- Raft now only accepts forwarded proposals if caught up as the new leader, limiting potentially unbounded log growth (#7809)
- Raft now correctly refuses concurrent membership changes if forwarded a peer removal from another node (#7809)
- The
max_consumerslimit of a stream can now be updated after stream creation (#7724) - The pending messages and bytes are now included in consumer unpin responses (#7815)
- Stream backups/snapshots are now streamed to clients with improved flow control, which should improve throughput and robustness, particularly over unreliable links, reducing the chance of backups failing due to flow control errors (#7828)
- Orphaned stream and consumer checks are now aligned with the metalayer snapshot logic (#7826)
- Wildcard filtering when loading messages is now considerably faster in the memory store (#7840, #7855)
- Metalayer snapshots now take place asynchronously when possible, such that JS API operations are not blocked while the snapshot is taking place (#7827, #7846)
- This behaviour can be disabled by setting
meta_compact_sync: truein thejetstreamconfiguration block
- This behaviour can be disabled by setting
- Consumers with a single subject filter no longer incorrectly use the multi-filter message lookups (#7856)
- The check for colliding stream subjects is now faster (#7870)
- Raft replica
lagandcurrentvalues in stream info, consumer info and/jszare now more consistent, no longer reporting incorrect values on follower nodes (#7885) - Num pending calculations for R1 consumers now happen asynchronously and should no longer block the metalayer (#7889)
Fixed
General
- Routed message arguments no longer escape to the heap, improving performance (#7867)
- Malformed functions or operations in user permissions templates or on invalid template expansion during auth should no longer result in a server panic
Leafnodes
- A crash when leafnodes with bad credentials performs an auth callout has been fixed (#7844)
- Receiving a leafnode subscription before negotiating compression should no longer result in a server panic
JetStream
- A filestore bug which could hold onto a lock when exiting after an error has been fixed (#7780)
- The filestore now always uses tombstones for recovering trailing deletes (#7782)
- Fixed a race condition when rebuilding block state during recovery (#7783)
- The filestore binary search for a message block now correctly sorts blocks that contain only tombstones (#7787)
- Fixed a data race for streams when acquiring the deduplication sequence (#7789)
- Raft now correctly checks the closed state when reporting if the node is current (#7793)
- Raft now sets the election timeout instead of the campaign timeout when leaving observer mode (#7793)
- The metalayer now tracks in-flight meta changes for invalid stream or consumer updates (#7798)
- The metalayer no longer incorrectly overwrites local consumer assignments before they are applied, which would result in them being omitted from the meta snapshot (#7798)
- The inactive threshold clean-up no longer leave lingering goroutines (#7799)
- Pooled publish message underlying buffer capacity is now reused correctly (#7790)
- Consumers with overlapping filter subjects where one is not a subset of the other are now allowed (#7810)
- The filestore now checksums after truncation on compressed or encrypted stores (#7816)
- The filestore no longer leaks locks in various error states (#7816)
- The filestore now correctly holds the lock during snapshotting on encrypted stores (#7816)
- The filestore now ensures that num pending calculations cannot overflow (#7816)
- The filestore now correctly recalculates the subject state as needed when finding last sequences (#7816)
- The filestore now sorts configured subjects when checking whether filters represent all of the configured filters (#7816)
- The filestore now avoids subject and header corruption in more cases (#7816)
- Consumer unpinning is now handled correctly when stepping down (#7819)
- Consumer unpinning now allows the next client to pick up the next pin without waiting for new messages (#7819)
- Fixed a race condition when remapping the underlying group of a replicated asset (#7820, #7883)
- An overflowed pull request when min pending or min ack pending is above the threshold is now handled correctly (#7795)
- Timers are no longer leaked when failing to set up mirrors, which resulted in high CPU usage (#7825)
- Monitor quit channels are created on demand, fixing cases where an asset restarts with a different underlying Raft group (#7837)
- Recovered streams and consumers are now correctly handled when not present in a metalayer catchup snapshot (#7824)
- Ensure that messages that have reached the max deliver state are preserved with the WorkQueue retention policy (#7845)
- An inconsistency with consumer naming between the current and legacy consumer create endpoints has been fixed (#7848)
- The Raft layer no longer incorrectly reverts the last snapshot applied sequence when truncating uncommitted entries after a catchup snapshot (#7849)
- The Raft layer no longer incorrectly restores the cluster size to 1 at startup, which could result in an isolated node incorrectly winning a single-node election (#7850)
- The memory store correctly refreshes the last sequence of a subject in the subject state tracking (#7865)
- Tiered reservations are now handled more consistently, fixing issues where replicated assets could be over-counted and where reservations were incorrectly applied on recovery (#7880)
- When scaling down a replicated consumer to R1, the correct consumer name is now used in the request where no durable name is set (#7891)
- Consumer deletion will now retry correctly when erroring with a directory not empty error (#7886)
- The
store_max_stream_bytesandmemory_max_stream_bytesare no longer incorrectly applied when determining whether account resource limits have been exceeded, fixing a long-standing bug where it would incorrectly limit total reservations (#7895) - A race condition in the memory store when updating the delete map has been fixed (#7897)
- Stream source checks are now enforced correctly when from a different account or domain (#7903)
- Consumer assignments no longer incorrectly handle or store transition state which could lead to issues on recovery or cause consumer state to be lost (#7905, #7908)
MQTT
- SUB and UNSUB packets now correctly detect and reject the Packet Identifier being set to 0 (#7805)
WebSockets
- Fix invalid parsing of 64-bit payload lengths, which could lead to a server panic
- Correctly reject compressed frames when compression was not negotiated as a part of the handshake
- The
Originheader validation now validates the protocol scheme as well as host and port - Gracefully handle failed connection upgrades
- The
CLOSEframe lengths and status codes are now validated correctly - The compressor state is correctly reset when a max payload error occurs
- Buffers are now correctly reused, reducing memory pressure (#7901)
- Empty compressed buffers should no longer result in a server panic