redis/redis-py · error · ValueError
Cannot create cache key.
Error message
Cannot create cache key.
What it means
Raised in CacheProxyConnection.send_command (connection.py:1779-1780) when the command is deemed cacheable by the cache (is_cachable returned True) but the caller did not pass keys=... . To build a CacheKey the proxy needs the keys the command operates on; if they are absent it cannot identify the cache entry, so it raises ValueError. This is an internal/library-side contract: cacheable commands must be dispatched with their keys.
Solutions
- Ensure cacheable read commands are sent through the standard client API that supplies keys (e.g. r.get('k') not raw conn.send_command('GET')).
- If using send_command directly with caching on, pass keys=('k',) for GET-style commands.
- Review your cache config's cacheable-command list and remove commands you dispatch without keys.
- Report/fix the command path so keys are propagated to the cache proxy.
Example fix
# before (with caching on)
conn.send_command('GET', 'mykey') # no keys kwarg
# after
conn.send_command('GET', 'mykey', keys=('mykey',)) Defensive patterns
Strategy: validation
Validate before calling
# When caching is on, route reads through the high-level API or pass keys
if caching_enabled:
val = r.get('mykey') # client supplies keys
else:
conn.send_command('GET', 'mykey') # direct is fine without cache
# If you must call send_command directly with caching on:
conn.send_command('GET', 'mykey', keys=('mykey',)) Type guard
def has_keys_kwarg(kwargs: dict) -> bool:
return kwargs.get('keys') is not None Try / catch
try:
conn.send_command('GET', 'mykey', keys=('mykey',))
except ValueError as e:
if 'Cannot create cache key' in str(e):
conn.send_command('GET', 'mykey', keys=('mykey',))
else:
raise Prevention
- Always pass keys= for cacheable commands when bypassing the client API.
- Keep the cacheable-command set aligned with commands you actually dispatch with keys.
- Prefer the high-level r.get/r.hget API so keys are propagated automatically.
When it happens
Trigger: The cache proxy decides a command is cacheable (a read command configured as cacheable) but send_command was invoked without the keys kwarg that the proxy uses to build CacheKey. Typically hit by the higher-level client layer failing to pass keys for a read command when caching is enabled.
Common situations: A read command routed through the cache proxy without keys metadata (custom command path, a command not yet plumbed to carry keys), or a misconfiguration of which commands are cacheable.
Related errors
- Cache must implement CacheInterface
- Evictions count is above cache size
- Given entry does not belong to the cache
- Prefix can only be used with bcast
- ACL LOG count must be an integer
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/4f2d6b101093029a.
Report an issue: GitHub.
Appendix: source
Thrown at redis/connection.py:1780
# next read_response does not try to cache their reply under a stale key.
self._current_command_cache_key = None
self._conn.send_packed_command(command)
def send_command(self, *args, **kwargs):
self._process_pending_invalidations()
with self._cache_lock:
# Command is write command or not allowed
# to be cached.
if not self._cache.is_cachable(
CacheKey(command=args[0], redis_keys=(), redis_args=())
):
self._current_command_cache_key = None
self._conn.send_command(*args, **kwargs)
return
if kwargs.get("keys") is None:
raise ValueError("Cannot create cache key.")
# Creates cache key.
self._current_command_cache_key = CacheKey(
command=args[0], redis_keys=tuple(kwargs.get("keys")), redis_args=args
)
with self._cache_lock:
# We have to trigger invalidation processing in case if
# it was cached by another connection to avoid
# queueing invalidations in stale connections.
if self._cache.get(self._current_command_cache_key):
entry = self._cache.get(self._current_command_cache_key)
with self._pool_lock:
while entry.connection_ref.can_read():
try:
entry.connection_ref.read_response(
push_request=True,View on GitHub (pinned to 6a6b581b48)