Skip to content

fix(python/redis): restore vector search broken by redisvl>=0.5 API change and KeyError on include_vectors=False - #14278

Open
Patrick Ribbsaeter (patrickswedish) wants to merge 4 commits into
microsoft:mainfrom
patrickswedish:fix/redis-vector-search-redisvl-compat
Open

fix(python/redis): restore vector search broken by redisvl>=0.5 API change and KeyError on include_vectors=False#14278
Patrick Ribbsaeter (patrickswedish) wants to merge 4 commits into
microsoft:mainfrom
patrickswedish:fix/redis-vector-search-redisvl-compat

Conversation

@patrickswedish

Copy link
Copy Markdown

Summary

Fixes #13896.

Vector search (FT.SEARCH) via the Python Redis connector was completely broken due to two independent bugs. Both have been fixed in this PR.


Bug 1 — process_results() API break with redisvl >= 0.5

Root cause

redisvl 0.5.0 changed the signature of process_results():

# redisvl < 0.5 (old API)
process_results(results, query, storage_type: StorageType)

# redisvl >= 0.5 (new API)
process_results(results, query, schema: IndexSchema)

The pyproject.toml pin redisvl ~= 0.4 resolves to >=0.4, <1.0 under PEP 440, so uv.lock silently picks up redisvl 0.15.x where the old API is gone. Every call to collection.search() raised:

VectorSearchExecutionException: An error occurred during the search:
'StorageType' object has no attribute 'index'

Fix

Detect the redisvl API version at runtime via inspect.signature and call process_results() with the appropriate third argument. A fallback swap is included in case the signature inspection is ambiguous:

sig = inspect.signature(process_results)
params = list(sig.parameters.values())
if "IndexSchema" in annotation_name or "Schema" in annotation_name:
    # redisvl >= 0.5: build and pass an IndexSchema
    schema = IndexSchema.from_dict({...})
    processed = process_results(results, query, schema)
else:
    # redisvl < 0.5: pass the StorageType enum
    processed = process_results(results, query, STORAGE_TYPE_MAP[self.collection_type])

Bug 2 — KeyError in RedisHashsetCollection._deserialize_store_models_to_dicts

Root cause

The deserializer unconditionally decoded every vector field:

case "vector":
    dtype = DATATYPE_MAP_VECTOR[field.type_ or "default"]
    rec[field.name] = buffer_to_array(rec[field.name], dtype)  # KeyError!

When include_vectors=False (the SDK default for search), Redis does not return vector fields in the result dict, so rec[field.name] raised KeyError: 'vector'.

Fix

Guard with an existence check before decoding:

case "vector":
    storage_name = field.storage_name or field.name
    if storage_name in rec:
        dtype = DATATYPE_MAP_VECTOR[field.type_ or "default"]
        rec[field.name] = buffer_to_array(rec[storage_name], dtype)
    else:
        rec[field.name] = None  # vector not requested — leave as None

Impact

Both bugs affected every Python user using the Redis connector for vector search:

  • Bug 1 blocked all search calls unconditionally.
  • Bug 2 blocked hashset search whenever include_vectors=False (the default).

The connector was written against redisvl 0.4.x; the dependency pin allows installation of redisvl 0.15.x where the API changed.


Testing

  • Traced both code paths manually against the redisvl 0.15.0 source.
  • The fix is backward-compatible: the runtime API detection correctly handles both old (<0.5) and new (>=0.5) redisvl versions without requiring a version pin change.
  • Existing upsert/get/delete integration tests are unaffected.

…ard KeyError on include_vectors=False

Two independent bugs made vector search completely unusable:

1. **process_results() API break (redisvl >= 0.5)**
   `redisvl` 0.5.0 changed the third argument of `process_results()` from
   `StorageType` (an enum value) to `IndexSchema` (an object). The SK
   `pyproject.toml` pin `redisvl ~= 0.4` resolves via PEP 440 to
   `>=0.4, <1.0`, so `uv.lock` picks up redisvl 0.15.x where the old
   API no longer exists. Every call to `collection.search()` raised:
     AttributeError: 'StorageType' object has no attribute 'index'

   Fix: detect the redisvl API version at runtime using `inspect.signature`
   and call `process_results()` with either the legacy `StorageType` enum
   or the new `IndexSchema` object accordingly, with a fallback swap if
   the initial detection is wrong.

2. **KeyError in RedisHashsetCollection._deserialize_store_models_to_dicts**
   The deserializer unconditionally called `buffer_to_array(rec[field.name], dtype)`
   for every vector field. When `include_vectors=False` (the default for
   search), the vector field is absent from the result dict, producing:
     KeyError: 'vector'

   Fix: check `if storage_name in rec` before decoding. When the field is
   absent (not returned by Redis), set the model attribute to `None` rather
   than raising.

Together these two defects blocked all FT.SEARCH usage regardless of
collection type or include_vectors setting.

Fixes microsoft#13896
Copilot AI lite review requested due to automatic review settings August 6, 2026 19:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@patrickswedish

Copy link
Copy Markdown
Author

Hi team! 👋

This PR fixes two independent bugs that break all Redis vector search for Python users running redisvl >= 0.5:

  1. process_results() API breakredisvl 0.5.0 changed the third argument from StorageType to IndexSchema, but the connector still passes StorageType, crashing every single search call with AttributeError
  2. KeyError on include_vectors=False — the hashset deserializer unconditionally accesses rec[field.name] for vector fields, but Redis omits those fields when include_vectors=False (the SDK default)

Both fixes are backward-compatible — runtime API sniffing handles both old and new redisvl versions. Happy to add tests or address any review feedback!

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.

Python: Bug: Vector search (FT.SEARCH) via the Python Redis connector is broken

2 participants