Skip to content

fix: keep vector fields in from_existing on RESP2 unified FT.INFO replies - #742

Open
desty wants to merge 1 commit into
redis:mainfrom
desty:fix/from-existing-resp2-unified-vector-flags
Open

desty wants to merge 1 commit into
redis:mainfrom
desty:fix/from-existing-resp2-unified-vector-flags

Conversation

@desty

@desty desty commented Sep 24, 2026 •

Copy link
Copy Markdown

Fixes #712

Problem

With redis-py 8 on a RESP2 connection created with legacy_responses=False, FT.INFO puts vector params into the field's flags list:

{'identifier': 'h', 'attribute': 'h', 'type': 'VECTOR',
 'flags': ['algorithm', 'HNSW', 'data_type', 'FLOAT32', 'dim', 8,
           'distance_metric', 'L2', 'M', 24, 'ef_construction', 300, 'INDEXMISSING']}

The dict branch of parse_vector_attrs skipped flags entirely. It found no dims and returned None, and convert_index_info_to_schema then dropped the field with a bare continue. As a result, SearchIndex.from_existing() + create() silently rebuilt the index without its vector fields.

Changes

  1. The dict branch of parse_vector_attrs now unpacks key/value pairs from flags. It skips valueless modifiers such as INDEXMISSING; I checked on Redis 8.4 that INDEXMISSING is appended as a bare token after the pairs. Top-level keys still take precedence, so RESP3 replies (params at top level, empty flags) behave as before.
  2. When a vector field is skipped, a warning now names the field and the index, so the skip is no longer silent.

Testing

  • Reproduced against redis:8.4 + redis-py 8.1.0 with a FLAT and an HNSW (m=24, ef_construction=300) vector field. Before this change, from_existing returned ['cat', 'text'] for protocol=2, legacy_responses=False. After it, all three client configurations (protocol=2, protocol=2, legacy_responses=False, protocol=3) recover the identical schema, including the HNSW params.
  • New unit tests in tests/unit/test_convert_index_info.py: flags unpacking with a trailing INDEXMISSING, and the skip warning. Both fail on main and pass here.
  • make format and make check-types pass. Running tests/unit (excluding test_mcp) plus tests/integration/test_connection.py gives the same result as on main: the pre-existing test_repr failures and google_genai optional-dependency errors, which are unrelated to this change, plus the 2 new tests passing.

AI disclosure: this change was prepared with an AI coding assistant (Claude Code). I reviewed the diff and ran the tests above.

🤖 Generated with Claude Code


Note

Medium Risk
Changes index schema reconstruction from FT.INFO for vector fields; incorrect parsing could still misrepresent indexes on recreate, but scope is limited to a known redis-py 8 RESP2 reply shape.

Overview
Fixes silent loss of vector fields when rebuilding schemas from FT.INFO under redis-py 8 on RESP2 with legacy_responses=False, where vector parameters are encoded as key/value pairs inside the field's flags list (sometimes followed by bare modifiers like INDEXMISSING).

parse_vector_attrs now walks those flags pairs when attributes arrive as a dict, skipping valueless FT.INFO modifiers via _VECTOR_VALUELESS_FLAGS, while still preferring top-level keys so RESP3-style replies are unchanged. When vector attributes still cannot be parsed, convert_index_info_to_schema logs a warning naming the field and index instead of dropping the field quietly—restoring correct behavior for SearchIndex.from_existing() / index recreation.

Unit tests cover RESP2 unified flags unpacking (including HNSW params and trailing INDEXMISSING) and the new skip warning.

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

…lies

With redis-py 8, protocol=2 and legacy_responses=False, FT.INFO packs
vector params into the field's flags list. parse_vector_attrs ignored
flags, found no dims, and the caller dropped the field without a trace,
so from_existing() + create() rebuilt the index without its vectors.

Unpack key/value pairs from flags (skipping valueless modifiers such as
INDEXMISSING), and log a warning when a vector field is skipped.

Fixes redis#712

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SearchIndex.from_existing silently drops vector fields on a RESP2 connection with legacy_responses=False

1 participant