Skip to content

Python: do not report an unreachable Redis as a missing index - #14474

Open
Eric Del Orefice (ericdelorefice) wants to merge 3 commits into
microsoft:mainfrom
ericdelorefice:fix/redis-collection-exists-specific-exception
Open

Eric Del Orefice (ericdelorefice) wants to merge 3 commits into
microsoft:mainfrom
ericdelorefice:fix/redis-collection-exists-specific-exception

Conversation

@ericdelorefice

Copy link
Copy Markdown

Motivation and Context

RedisCollection.collection_exists caught every exception and returned False, and ensure_collection_deleted gates the drop on that answer:

async def ensure_collection_deleted(self, **kwargs) -> None:
    exists = await self.collection_exists()
    if exists:
        await self.redis_database.ft(self.collection_name).dropindex(**kwargs)
    else:
        logger.debug("Collection does not exist, skipping deletion.")

collection_exists() reaches Redis to answer, so a timeout, an authentication failure or an unreachable node all return False. ensure_collection_deleted then logs at debug level and returns normally, and the caller is told the collection is gone when it is still there.

The ChromaCollection connector already draws this distinction - it handles a genuinely absent collection quietly and raises VectorStoreOperationException for anything else. This brings the Redis connector in line with it.

Fixes #14473

Description

collection_exists now catches ResponseError, which is what redis-py raises when FT.INFO reports an unknown index. ConnectionError, TimeoutError and AuthenticationError are siblings of ResponseError rather than subclasses, so they propagate instead of being reported as an absent index.

On the test change: test_collection_exists_false used a bare Exception as the side effect. Redis does not raise that, and it matched a timeout as readily as a missing index, so the test could not tell the two cases apart. It now raises ResponseError, which is the real behaviour, and a new test asserts that a connection error reaches the caller.

I checked that the new test fails without the source change, so it is testing what it claims to.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • I didn't break anyone 😄
  • I have added tests that prove my fix is effective
  • All unit tests pass locally: pytest tests/unit/connectors/memory/test_redis_store.py passes 27/27

RedisCollection.collection_exists caught every exception and returned
False. ensure_collection_deleted gates the drop on that answer, so a
timeout, an authentication failure or an unreachable node made it log at
debug level and return successfully having deleted nothing. The caller
is told the collection is gone when it is not.

Catch ResponseError, which is what redis-py raises when FT.INFO reports
an unknown index. ConnectionError, TimeoutError and AuthenticationError
are siblings of ResponseError rather than subclasses, so they now
propagate.

The ChromaCollection connector already distinguishes these two cases:
it handles a genuinely absent collection quietly and raises
VectorStoreOperationException for anything else.

The existing test used a bare Exception, which is not what Redis raises
and matched a timeout just as readily. It now uses ResponseError, and a
new test asserts a connection error reaches the caller.

Fixes microsoft#14473
@ericdelorefice

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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 review overview

🟡 Changes recommended

Redis imports are incorrectly ordered in both reviewed files and will fail configured Ruff checks.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
What changed in this PR

This pull request ensures Redis connection failures are not reported as missing indexes.

Changes:

  • Handles ResponseError for missing indexes.
  • Adds tests for connection-error propagation.
File Summary
python/​semantic_kernel/​connectors/​redis.py Updates Redis index existence error handling.
python/​tests/​unit/​connectors/​memory/​test_redis_store.py Adds targeted exception tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 17 to 20
from redis.exceptions import ResponseError
from redis.commands.search.field import Field as RedisField
from redis.commands.search.field import NumericField, TagField, TextField, VectorField
from redis.commands.search.index_definition import IndexDefinition, IndexType
Comment on lines +15 to +16
from redis.exceptions import ConnectionError as RedisConnectionError
from redis.exceptions import ResponseError
redis.exceptions sorts after redis.commands, and in the test file the
new imports split the third-party block from the semantic_kernel one.
Ruff's isort gate is enabled in pyproject.toml, so both would have
failed lint.

ruff check and ruff format now pass on both files, and the unit tests
still pass 27/27.
@ericdelorefice

Copy link
Copy Markdown
Author

Good catch on both, and you are right. Fixed and pushed.

redis.exceptions sorts after redis.commands, so the connector import was in the wrong place within the third-party group, and in the test file the two new imports split the third-party block from the semantic_kernel one. Ruff's isort gate is enabled in python/pyproject.toml, so both would have failed lint rather than merely looking untidy.

ruff check and ruff format --check now pass on both files, and pytest tests/unit/connectors/memory/test_redis_store.py still passes 27/27.

One correction on the report itself: the second instance is at line 20 of the test file, not line 291 of the connector. Line 291 is the collection_exists change, which has no import in it.

@semantic-kernel-automation semantic-kernel-automation Bot added the python Pull requests for the Python Semantic Kernel label Sep 30, 2026

This branch was previously deployed

1 inactive deployment
github-app-auth — 1c46930a Deployed Sep 30, 2026 by ericdelorefice via add_label #29201
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

Development

Successfully merging this pull request may close these issues.

Python: RedisCollection.ensure_collection_deleted can return successfully without deleting the index

2 participants