🐛 Bug Fix
- fix: check index existence with FT.INFO instead of listing every index #672 @vishal-bala
- fix: de-duplicate cursor keys in update_by_filter #671 @vishal-bala
- fix: bound Timestamp date comparisons to the whole UTC day #670 @vishal-bala
- fix(mcp): escape text filter values and reject an empty projection #667 @vishal-bala
- fix: anchor Timestamp date filters to the UTC day #666 @vishal-bala
- fix: negate the day range in Timestamp != date filters #655 @TheSaiEaranti
- fix: tolerate matched docs with missing field payload (Redis 8.8 expiry race) #653 @vishal-bala
📝 Documentation
- docs: add exception reference and error handling guide #654 @TheSaiEaranti
- chore(ci): stop notebook tests wasting 33 minutes on a blocking cell #665 @vishal-bala
🔩 Dependency Updates
- chore(mcp): upper-bound the MCP dependency pins #669 @vishal-bala
- chore(deps): bump the uv group across 1 directory with 14 updates #664 (@dependabot[bot] @vishal-bala
Notes
Timestamp date filters now return different rows (affected versions 0.5.1–0.25.0). With a bare date or date-only string, != matched the day it was asked to exclude, > behaved like >=, and <= behaved like <. Day boundaries also followed the host timezone rather than UTC, so the same filter resolved differently by machine. All of it failed silently. If you compensated for the old behavior, remove the workaround; if you assert on generated query strings, expect them to change. datetime, full ISO string, and Unix timestamp filters were never affected.
exists() now raises RedisSearchError instead of leaking raw redis-py exceptions. create() already wrapped every other Redis failure this way; the existence check was the one path that escaped. Code catching redis.exceptions.ResponseError around create() — or around a SemanticCache, MessageHistory, SemanticMessageHistory, or SemanticRouter constructor, all of which call create() — should catch RedisSearchError and read __cause__ for the original. This includes NoPermissionError handlers, since that subclasses ResponseError.