Repository navigation
Read HELLO "server" before trusting "version" as the Redis API version - #3279
Merged
Merged
Conversation
#3278) Valkey reports its own version as HELLO "version" ("server" => "valkey", "version" => "9.1.2") while INFO still says redis_version:7.2.4; Garnet keeps "version" as the Redis API version ("server" => "redis") and adds "garnet_version". Both the interactive and subscription connections issue HELLO, so the detected version depended on whether the last reply processed was HELLO or INFO, and version-gated commands (DELEX for LockRelease) were sent to servers that don't have them. Now "version" only sets the Redis API version when "server" is redis; for a recognised non-Redis server it feeds the product variant instead, and for an unrecognised server it is ignored. A "<vendor>_version" HELLO field sets the product variant in the Garnet shape. The in-process test server can emulate both measured shapes, and a HELLO-only test (INFO disabled) pins the rule down on RESP2 and RESP3.
Parse it as a Version (no string) once we know "server" is redis; only the vendor path, which stores the string anyway, materializes it.
Adds Format.TryParseVersion(ReadOnlySpan<byte>): net10.0 has a built-in UTF-8 Version.TryParse; elsewhere a Utf8Parser loop over the dotted components, so no char transcoding and, downlevel, no string. The HELLO handler uses it via the function-pointer TryParseScalar overload; a parity test keeps it in step with the char/string overloads.
…d the gate normalisation System.Version treats "7.4" as (7, 4, -1, -1) and "7.4.0" as (7, 4, 0, -1); the UTF-8 overload must produce the same raw parts as the char/string overloads, and IsAtLeast/IsEqual must then treat the unspecified parts as zero.
The goal is identical results to the pre-existing char path for identical text, whatever System.Version does with it (-1 for unspecified parts, whitespace and sign tolerance per part), not a tidier parser. net10.0 fast-paths the built-in UTF-8 Version.TryParse; anything it rejects, and every other TFM, transcodes and calls the char overload. On .NET Framework that still allocates a string, which is acceptable. The parity test now covers the whitespace/sign cases.
FloatingMilkshake
pushed a commit
to FloatingMilkshake/MechanicalMilkshake
that referenced
this pull request
Oct 24, 2026
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [StackExchange.Redis](https://seredis.dev/) ([source](https://github.com/StackExchange/StackExchange.Redis)) | nuget | patch | `3.4.0` → `3.4.20` | --- ### Release Notes <details> <summary>StackExchange/StackExchange.Redis (StackExchange.Redis)</summary> ### [`v3.4.20`](https://github.com/StackExchange/StackExchange.Redis/releases/tag/3.4.20) [Compare Source](StackExchange/StackExchange.Redis@3.4.5...3.4.20) #### Stability improvements - Do not abandon a connection attempt before ConnectTimeout has elapsed by [@​mgravell](https://github.com/mgravell) in [#​3277](StackExchange/StackExchange.Redis#3277) - Read HELLO "server" before trusting "version" as the Redis API version by [@​mgravell](https://github.com/mgravell) in [#​3279](StackExchange/StackExchange.Redis#3279) - Sentinel soft-fail follow-ups: discovery failure as RedisConnectionException, late sentinel init, clear LastException by [@​mgravell](https://github.com/mgravell) in [#​3280](StackExchange/StackExchange.Redis#3280) - Sentinel: re-resolve the primary when it is demoted on a healthy connection by [@​rebaseandpanic](https://github.com/rebaseandpanic) in [#​3281](StackExchange/StackExchange.Redis#3281) - Route as a cluster only with a slot map; take HELLO mode/role from the interactive connection only by [@​mgravell](https://github.com/mgravell) in [#​3285](StackExchange/StackExchange.Redis#3285) - Fail connection-dropped commands with RedisConnectionException, never a raw transport exception or a cancellation by [@​mgravell](https://github.com/mgravell) in [#​3287](StackExchange/StackExchange.Redis#3287) - Connection groups: a member answering LOADING triggers an immediate re-probe and re-select by [@​mgravell](https://github.com/mgravell) in [#​3289](StackExchange/StackExchange.Redis#3289) - IBatch: complete commands refused by a poisoned connection; divert a batch's tail on reconnect by [@​mgravell](https://github.com/mgravell) in [#​3286](StackExchange/StackExchange.Redis#3286) - Give multi-message sub-commands and injected prefix commands a write time by [@​mgravell](https://github.com/mgravell) in [#​3293](StackExchange/StackExchange.Redis#3293) - Send primary-only commands to the primary when the caller prefers a replica by [@​AsadIqbal-Dev](https://github.com/AsadIqbal-Dev) in [#​3291](StackExchange/StackExchange.Redis#3291) #### Maintenance - Tests: stabilise two recurring Windows CI flakes (hash-field expiry clock skew, backlog counter quiescence) by [@​mgravell](https://github.com/mgravell) in [#​3288](StackExchange/StackExchange.Redis#3288) - Tests: don't race the connect's own reconfigures in AllClusterCommandsRefusedIsQuiet by [@​mgravell](https://github.com/mgravell) in [#​3290](StackExchange/StackExchange.Redis#3290) - Refresh package pins: 10.0.13 servicing family and tooling by [@​mgravell](https://github.com/mgravell) in [#​3294](StackExchange/StackExchange.Redis#3294) - xunit.v3 4.0 on Microsoft.Testing.Platform by [@​mgravell](https://github.com/mgravell) in [#​3295](StackExchange/StackExchange.Redis#3295) - StyleCop.Analyzers 1.3.151-beta, and the tidy-up it asks for by [@​mgravell](https://github.com/mgravell) in [#​3296](StackExchange/StackExchange.Redis#3296) #### New Contributors - [@​AsadIqbal-Dev](https://github.com/AsadIqbal-Dev) made their first contribution in [#​3291](StackExchange/StackExchange.Redis#3291) **Full Changelog**: <StackExchange/StackExchange.Redis@3.4.5...3.4.20> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODEuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.milkshake.services/FloatingMilkshake/MechanicalMilkshake/pulls/10 Reviewed-by: Milkshake <me@floatingmilkshake.com>
FloatingMilkshake
pushed a commit
to FloatingMilkshake/Azusa
that referenced
this pull request
Oct 24, 2026
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [StackExchange.Redis](https://seredis.dev/) ([source](https://github.com/StackExchange/StackExchange.Redis)) | nuget | patch | `3.4.0` → `3.4.20` | --- ### Release Notes <details> <summary>StackExchange/StackExchange.Redis (StackExchange.Redis)</summary> ### [`v3.4.20`](https://github.com/StackExchange/StackExchange.Redis/releases/tag/3.4.20) [Compare Source](StackExchange/StackExchange.Redis@3.4.5...3.4.20) #### Stability improvements - Do not abandon a connection attempt before ConnectTimeout has elapsed by [@​mgravell](https://github.com/mgravell) in [#​3277](StackExchange/StackExchange.Redis#3277) - Read HELLO "server" before trusting "version" as the Redis API version by [@​mgravell](https://github.com/mgravell) in [#​3279](StackExchange/StackExchange.Redis#3279) - Sentinel soft-fail follow-ups: discovery failure as RedisConnectionException, late sentinel init, clear LastException by [@​mgravell](https://github.com/mgravell) in [#​3280](StackExchange/StackExchange.Redis#3280) - Sentinel: re-resolve the primary when it is demoted on a healthy connection by [@​rebaseandpanic](https://github.com/rebaseandpanic) in [#​3281](StackExchange/StackExchange.Redis#3281) - Route as a cluster only with a slot map; take HELLO mode/role from the interactive connection only by [@​mgravell](https://github.com/mgravell) in [#​3285](StackExchange/StackExchange.Redis#3285) - Fail connection-dropped commands with RedisConnectionException, never a raw transport exception or a cancellation by [@​mgravell](https://github.com/mgravell) in [#​3287](StackExchange/StackExchange.Redis#3287) - Connection groups: a member answering LOADING triggers an immediate re-probe and re-select by [@​mgravell](https://github.com/mgravell) in [#​3289](StackExchange/StackExchange.Redis#3289) - IBatch: complete commands refused by a poisoned connection; divert a batch's tail on reconnect by [@​mgravell](https://github.com/mgravell) in [#​3286](StackExchange/StackExchange.Redis#3286) - Give multi-message sub-commands and injected prefix commands a write time by [@​mgravell](https://github.com/mgravell) in [#​3293](StackExchange/StackExchange.Redis#3293) - Send primary-only commands to the primary when the caller prefers a replica by [@​AsadIqbal-Dev](https://github.com/AsadIqbal-Dev) in [#​3291](StackExchange/StackExchange.Redis#3291) #### Maintenance - Tests: stabilise two recurring Windows CI flakes (hash-field expiry clock skew, backlog counter quiescence) by [@​mgravell](https://github.com/mgravell) in [#​3288](StackExchange/StackExchange.Redis#3288) - Tests: don't race the connect's own reconfigures in AllClusterCommandsRefusedIsQuiet by [@​mgravell](https://github.com/mgravell) in [#​3290](StackExchange/StackExchange.Redis#3290) - Refresh package pins: 10.0.13 servicing family and tooling by [@​mgravell](https://github.com/mgravell) in [#​3294](StackExchange/StackExchange.Redis#3294) - xunit.v3 4.0 on Microsoft.Testing.Platform by [@​mgravell](https://github.com/mgravell) in [#​3295](StackExchange/StackExchange.Redis#3295) - StyleCop.Analyzers 1.3.151-beta, and the tidy-up it asks for by [@​mgravell](https://github.com/mgravell) in [#​3296](StackExchange/StackExchange.Redis#3296) #### New Contributors - [@​AsadIqbal-Dev](https://github.com/AsadIqbal-Dev) made their first contribution in [#​3291](StackExchange/StackExchange.Redis#3291) **Full Changelog**: <StackExchange/StackExchange.Redis@3.4.5...3.4.20> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODEuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.milkshake.services/FloatingMilkshake/Azusa/pulls/10 Reviewed-by: Milkshake <me@floatingmilkshake.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3278.
Problem
Since 3.4.0 the
HELLOreply has been a source of the server version, and both the interactive and subscription connections issueHELLO. The handler assignedversionstraight to the Redis API version, but the two conventions in the wild differ (measured against real servers):serverversionredis7.4.3(Redis API version)garnet_version => 2.2.2valkey9.1.2(Valkey's own version)redis_version:7.2.4On Valkey the detected version therefore depended on whether the last reply processed was
HELLO(9.1.2) orINFO(7.2.4), so version-gated commands (e.g.DELEXinLockRelease) were sometimes sent to a server that does not have them.Rule
Decided once the whole
HELLOmap has been read:server => redis(or absent):versionis the Redis API version; a<vendor>_versionkey, if present, sets the product variant (Garnet shape).serveris a recognised non-Redis name (valkey,redict, ...):versionis the vendor version and only feeds the product variant; the API version is left toINFO'sredis_version.serveris unrecognised:versionis ignored (logged). Conservative by design: ifINFOis unavailable too, the version falls back toDefaultVersionrather than guessing.HELLOnever touches the product variant, so it cannot clobberINFO's KeyDB detection (which comes fromexecutable, not a*_versionkey).Verification
HelloServerName,HelloVersionString,HelloExtraFields).ProductVariantUnitTestsandValkeyUnitTestsrun per protocol and assert the API version as well as the variant.DetectProductVariantFromHelloAlonedisablesINFOsoHELLOis the only source; it fails deterministically on RESP2 and RESP3 with the fix reverted. The test vendor version is now9.1.2rather than1.2.3-preview4, because an unparseable version was hiding the bug.Build.csprojRelease build withCI=trueis green.