Skip to content

Python: fix(python/redis): fix FT.CREATE prefix format and silent delete failure#13907

Open
EaCognitive wants to merge 2 commits intomicrosoft:mainfrom
EaCognitive:fix-python-redis-connector
Open

Python: fix(python/redis): fix FT.CREATE prefix format and silent delete failure#13907
EaCognitive wants to merge 2 commits intomicrosoft:mainfrom
EaCognitive:fix-python-redis-connector

Conversation

@EaCognitive
Copy link
Copy Markdown

Fixes #13894
Fixes #13904

Problem

The Python Redis connector in Semantic Kernel had two critical bugs:

  1. Index Creation (Python: Bug: Redis connector sends malformed FT.CREATE PREFIX (one prefix per character of collection name) #13894): The IndexDefinition prefix was passed as a string instead of a list, causing Redis to malform the index prefix. This effectively broke vector search (RAG) on Redis.
  2. Silent Delete Failure (Python: Bug: RedisJsonCollection.delete() silently fails when prefix_collection_name_to_key_names is enabled #13904): The RedisJsonCollection._inner_delete method used raw keys instead of calling _get_redis_key(). This caused deletion to silently fail when prefix_collection_name_to_key_names was enabled.

Solution

  1. Wrap Prefix: Wrapped the collection prefix in a list for IndexDefinition.
  2. Correct Key Prefixing: Updated _inner_delete to use the _get_redis_key() helper for all keys.

Changes

  • python/semantic_kernel/connectors/redis.py: Fixed prefix formatting and key resolution in deletion logic.

Verification

  • Verified that IndexDefinition now receives a list of prefixes.
  • Verified that deletion logic now correctly applies collection prefixes.

@EaCognitive EaCognitive requested a review from a team as a code owner April 21, 2026 20:43
@moonbox3 moonbox3 added the python Pull requests for the Python Semantic Kernel label Apr 21, 2026
@github-actions github-actions Bot changed the title fix(python/redis): fix FT.CREATE prefix format and silent delete failure Python: fix(python/redis): fix FT.CREATE prefix format and silent delete failure Apr 21, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 93%

✓ Correctness

Both changes are correct bug fixes. (1) The prefix parameter to IndexDefinition is changed from a string to a list, which matches the redis-py API expectation. (2) RedisJsonCollection._inner_delete now correctly applies _get_redis_key to prefix keys with the collection name, consistent with how _inner_get (line 699) and the sibling RedisHashsetCollection._inner_delete (line 581) already handle keys. Without this fix, JSON deletes would silently fail to find the correct keys.

✓ Security Reliability

Two bug fixes: (1) IndexDefinition prefix changed from string to list to match the redis-py API expectation, and (2) _inner_delete in the JSON-backed collection now correctly applies _get_redis_key() to prefix keys before deletion, consistent with the hash-backed collection's _inner_delete at line 581. Both changes are correct and improve reliability.

✗ Test Coverage

This PR fixes two bugs: (1) the prefix parameter in IndexDefinition is changed from a string to a list, and (2) RedisJsonCollection._inner_delete now correctly applies _get_redis_key to prepend the collection name prefix to keys before deletion. Both fixes align the behavior with the rest of the codebase. However, test coverage for these changes is insufficient. test_delete (line 274) only tests without prefix_collection_name_to_key_names=True and makes no assertions on the keys passed to the delete mock, meaning the JSON delete bug fix is not verified. Similarly, the ensure_collection_exists tests don't assert the prefix argument format passed to create_index. Both test_get and test_upsert already have prefix-parameterized variants, but test_delete does not.

✓ Design Approach

Both changes are correct, targeted bug fixes. The prefix change from a bare string to a single-element list correctly matches the redis-py IndexDefinition API contract. The _get_redis_key fix in RedisJsonCollection._inner_delete brings it in line with RedisHashsetCollection._inner_delete (line 581), which already applied the prefix transformation; without this fix, deletes silently do nothing when prefix_collection_name_to_key_names=True.

Flagged Issues

  • The _inner_delete fix for RedisJsonCollection (adding _get_redis_key) has no test with prefix_collection_name_to_key_names=True. The existing test_delete (line 274 of test_redis_store.py) only uses non-prefix collections and doesn't assert on the arguments passed to the mock. Compare with test_get (line 259) which parameterizes on prefix=True/Falsetest_delete should do the same, and should assert that the mock was called with the correctly prefixed keys.

Suggestions

  • Add a prefix-parameterized variant of test_delete for both hashset and JSON collections (similar to test_get), asserting that the delete mock receives keys prefixed with the collection name when prefix_collection_name_to_key_names=True.
  • Add an assertion in test_create_index that verifies the IndexDefinition passed to create_index has prefix as a list (e.g., ['test:']) rather than a string, to directly test the first fix in this PR.

Automated review by EaCognitive's agents

@override
async def _inner_delete(self, keys: Sequence[str], **kwargs: Any) -> None:
await asyncio.gather(*[self.redis_database.json().delete(key, **kwargs) for key in keys])
await asyncio.gather(*[self.redis_database.json().delete(self._get_redis_key(key), **kwargs) for key in keys])
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.

This bug fix is not covered by any test. The existing test_delete at line 274 of test_redis_store.py only uses collections with prefix_collection_name_to_key_names=False, so _get_redis_key returns the key unchanged. Please add a test that uses collection_with_prefix_json and asserts the mock's delete was called with 'test:id1' (the prefixed key).

@EaCognitive
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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

Labels

python Pull requests for the Python Semantic Kernel

Projects

None yet

2 participants