Skip to content

fix: ignore unknown fields in CLUSTER SHARDS response#3843

Merged
ndyakov merged 1 commit into
redis:masterfrom
madolson:ignore-unknown-cluster-shards-fields
Jun 4, 2026
Merged

fix: ignore unknown fields in CLUSTER SHARDS response#3843
ndyakov merged 1 commit into
redis:masterfrom
madolson:ignore-unknown-cluster-shards-fields

Conversation

@madolson

@madolson madolson commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

The CLUSTER SHARDS response parser errors on any unrecognized field, breaking clients whenever the server introduces new node or shard attributes.

The nodes field contains a list of all nodes within the shard. Each individual node is a map of attributes that describe the node. Some attributes are optional and more attributes may be added in the future. The current list of attributes:

id, endpoint, ip, hostname, port, tls-port, role, replication-offset, health

The parser should be forward-compatible. Unknown fields are now discarded via rd.DiscardNext(), the same pattern used elsewhere in this codebase (e.g., FunctionListCmd, ModuleLoadexConfig parsing).

Changes:

  • Replace fmt.Errorf on unknown node-level fields with rd.DiscardNext()
  • Replace fmt.Errorf on unknown shard-level fields with rd.DiscardNext()
  • Add unit tests verifying unknown fields (string, integer, array values) are silently skipped

Test plan

  • Unit tests cover unknown fields at both shard and node levels
  • Tests exercise string, integer, and array-typed unknown values
  • CI passes (no Go installed locally to verify)

Note

Medium Risk
Changes cluster topology parsing used for routing; incorrect discard logic could break cluster clients, but behavior aligns with existing DiscardNext patterns and is covered by new unit tests.

Overview
The CLUSTER SHARDS reply parser no longer fails when Redis returns unknown shard- or node-level attributes. Unrecognized keys are skipped with rd.DiscardNext() instead of returning fmt.Errorf, matching forward-compatibility used elsewhere (e.g. XInfo* parsers).

Tests assert that known slots / nodes data still parses when extra fields are present (string, integer, and array-valued unknown node fields).

Reviewed by Cursor Bugbot for commit 7f4fdaf. Bugbot is set up for automated code reviews on this repo. Configure here.

The CLUSTER SHARDS 'nodes' field contains a list of all nodes within
the shard. Each individual node is a map of attributes that describe
the node. Some attributes are optional and more attributes may be added
in the future.

Previously, the parser returned an error on any unrecognized field,
causing breakage whenever the server introduces new attributes. Now
unknown fields at both the shard level and node level are silently
discarded, matching the forward-compatible behavior already used
elsewhere in this codebase.

Signed-off-by: Madelyn Olson <[email protected]>
@jit-ci

jit-ci Bot commented Jun 3, 2026

Copy link
Copy Markdown

Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset.

In case there are security findings, they will be communicated to you as a comment inside the PR.

Hope you’ll enjoy using Jit.

Questions? Comments? Want to learn more? Get in touch with us.

@ndyakov

ndyakov commented Jun 3, 2026

Copy link
Copy Markdown
Member

Hello @madolson and thank you for this contribution. It makes sense to be forward compatible and ignore the unknown fields. Were there any specific ones that triggered this error for you? If so, does it make more sense to include them in the struct now?

Also, since we had a similar case for XInfoConsumersCmd -

// skip unknown fields
I was wondering does it make sense to have all the unknown fields in a map for such commands? What do you think?

@madolson

madolson commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

@ndyakov We hit while upgrade to Valkey 9.1. I understand that isn't Redis, but the documentation looks like they should be compatible for this dimensions, so better to make sure it doesn't break in the future!

I was wondering does it make sense to have all the unknown fields in a map for such commands? What do you think?

That makes sense to me! I'm just trying to scope down the change, but happy to make more.

@ndyakov ndyakov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good as it is.
@madolson no need to extend it at this time, there are other similar commands that try to parse the whole response and fail on unknown fields, which is not ideal. I am willing to include this change and take care of the rest when I decide on a proper approach. Thank you!

@ndyakov
ndyakov merged commit 974e717 into redis:master Jun 4, 2026
40 checks passed
rohitkumarankam pushed a commit to rohitkumarankam/forgejo that referenced this pull request Jun 11, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) | `v9.20.0` → `v9.20.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fredis%2fgo-redis%2fv9/v9.20.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fredis%2fgo-redis%2fv9/v9.20.0/v9.20.1?slim=true) |

---

### Release Notes

<details>
<summary>redis/go-redis (github.com/redis/go-redis/v9)</summary>

### [`v9.20.1`](https://github.com/redis/go-redis/releases/tag/v9.20.1): 9.20.1

[Compare Source](redis/go-redis@v9.20.0...v9.20.1)

This is a patch release containing bug fixes only. There are no new features or breaking changes; upgrading from 9.20.0 is a drop-in replacement.

#### 🚀 Highlights

##### RESP3 pub/sub message loss fixed

`PeekPushNotificationName` previously inspected only the bytes already buffered by `bufio`, so when a push frame header straddled a buffer fill boundary it could return a **truncated** notification name (e.g. `"messa"` instead of `"message"`). The push processor then mis-routed the frame and `ReadReply` silently dropped it, causing intermittent RESP3 pub/sub message loss. The peek now grows its window (36 bytes → up to 4 KiB) and reads more from the connection until the header is complete, cleanly separating incomplete prefixes from corrupt frames (including overflow-safe bulk-length handling). Fixes [#&#8203;3839](redis/go-redis#3839).

([#&#8203;3842](redis/go-redis#3842)) by [@&#8203;ndyakov](https://github.com/ndyakov)

#### 🐛 Bug Fixes

- **RESP3 push peeking**: `PeekPushNotificationName` no longer returns a truncated notification name when a push frame header spans a buffer boundary, preventing silent RESP3 pub/sub message loss (fixes [#&#8203;3839](redis/go-redis#3839)) ([#&#8203;3842](redis/go-redis#3842)) by [@&#8203;ndyakov](https://github.com/ndyakov)
- **`FT.HYBRID` vector params**: Vector data is now always sent via `PARAMS` with auto-generated param names (`__vector_param_N`, with collision avoidance) when `VectorParamName` is omitted, since Redis no longer accepts inline vector blobs; the `FTHybridOptions.Params` map is no longer mutated, so the same options struct can be reused across calls ([#&#8203;3844](redis/go-redis#3844)) by [@&#8203;ndyakov](https://github.com/ndyakov)
- **`CLUSTER SHARDS` forward compatibility**: Unknown shard- and node-level attributes in the `CLUSTER SHARDS` reply are now skipped via `DiscardNext()` instead of erroring, so clients keep working when the server introduces new fields ([#&#8203;3843](redis/go-redis#3843)) by [@&#8203;madolson](https://github.com/madolson)
- **PubSub double reconnect**: `PubSub.releaseConn` no longer reconnects twice when a connection is both unusable (or pending handoff) and reports a bad-connection error, avoiding a wasted connection establish-then-close cycle ([#&#8203;3833](redis/go-redis#3833)) by [@&#8203;cxljs](https://github.com/cxljs)

#### 👥 Contributors

We'd like to thank all the contributors who worked on this release!

[@&#8203;cxljs](https://github.com/cxljs), [@&#8203;madolson](https://github.com/madolson), [@&#8203;ndyakov](https://github.com/ndyakov)

***

**Full Changelog**: <redis/go-redis@v9.20.0...v9.20.1>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`)
- Automerge
  - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`)

🚦 **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](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMTQuNSIsInVwZGF0ZWRJblZlciI6IjQzLjIxNC41IiwidGFyZ2V0QnJhbmNoIjoiZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/13061
Reviewed-by: Mathieu Fenniak <[email protected]>
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