Skip to content

Fix Redis key generation to be stable across working directories - #27025

Merged
yuneng-berri merged 1 commit into
litellm_internal_stagingfrom
litellm_fix-redis-key-generation-d88e
May 1, 2026
Merged

Fix Redis key generation to be stable across working directories#27025
yuneng-berri merged 1 commit into
litellm_internal_stagingfrom
litellm_fix-redis-key-generation-d88e

Conversation

@mateo-berri

Copy link
Copy Markdown
Contributor

Relevant issues

Pre-Submission checklist

  • I have added testing in the tests directory
  • My PR's scope is isolated - fixes Redis key stability issue
  • Added comprehensive test case for the fix

Type

🐛 Bug Fix
✅ Test

Changes

Problem

The redis_key_for() function was generating different Redis keys for the same cassette file depending on the current working directory. This caused cache misses and inconsistent behavior when tests were run from different directories.

Solution

Modified redis_key_for() in tests/_vcr_redis_persister.py to:

  1. Convert the cassette path to an absolute path first
  2. Calculate the relative path from the repository root (stored in _REPO_ROOT) instead of the current working directory
  3. Handle edge cases where the path is outside the repo root by falling back to the basename

Testing

Added test_redis_key_is_stable_across_working_directories() in tests/llm_translation/test_vcr_redis_persister.py that:

  • Verifies the Redis key is identical when generated from the repo root, a subdirectory, and a temporary directory
  • Confirms the key format matches the expected pattern: litellm:vcr:cassette:tests/llm_translation/test_anthropic/test_streaming

This ensures VCR cassette caching works reliably regardless of where tests are executed from.

Slack Thread

Open in Web Open in Cursor 

`os.path.relpath` with no `start` arg uses the current working
directory, so running pytest from a subdirectory produced a
different Redis key than running from the repo root. CI-recorded
cassettes and locally-replayed runs would silently miss each
other's cache.

Anchor the path to the repo root (derived from `__file__`) so the
key is stable regardless of CWD.

https://claude.ai/code/session_018uCx7pcrkdUJZrCVMaTdPx
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented May 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri
mateo-berri marked this pull request as ready for review May 1, 2026 23:36
@mateo-berri
mateo-berri requested a review from yuneng-berri May 1, 2026 23:36
@greptile-apps

greptile-apps Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes redis_key_for() in tests/_vcr_redis_persister.py to produce a stable Redis key regardless of the current working directory by resolving all cassette paths to absolute and then relativizing against a module-level _REPO_ROOT constant computed from __file__. The accompanying test exercises three distinct working directories to confirm key stability.

Confidence Score: 4/5

Safe to merge; fix is correct for all practical cases and only has minor hardening gaps.

The fix is logically sound and well-tested. The only findings are P2: a basename-based fallback that could theoretically collide on Windows cross-drive scenarios, and use of abspath rather than realpath which could misfire when symlinks are involved. Neither affects the primary Linux/macOS CI path.

tests/_vcr_redis_persister.py — the fallback and symlink handling in redis_key_for.

Important Files Changed

Filename Overview
tests/_vcr_redis_persister.py Adds _REPO_ROOT constant computed from __file__ at import time; redis_key_for() now resolves paths to absolute first, then relativizes against _REPO_ROOT, with a ValueError fallback to basename for cross-drive Windows paths.
tests/llm_translation/test_vcr_redis_persister.py Adds test_redis_key_is_stable_across_working_directories which verifies key stability across three different working directories using monkeypatch.chdir; no network calls, correctly uses fakeredis for all other tests.

Reviews (1): Last reviewed commit: "fix(tests): anchor VCR redis cassette ke..." | Re-trigger Greptile

VCR_VERBOSE_ENV = "LITELLM_VCR_VERBOSE"
MAX_EPISODES_PER_CASSETTE = 50

_REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

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.

P2 os.path.abspath does not resolve symlinks, so _REPO_ROOT and a cassette path can represent the same physical location via different string prefixes (one through a symlink, one through the real path). In that case os.path.relpath(abs_path, start=_REPO_ROOT) produces a ../../… path which the subsequent lstrip("./") then silently mangles into a wrong key. Using os.path.realpath for both would make the prefix comparison reliable.

Suggested change
_REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_REPO_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))


def redis_key_for(cassette_path: str) -> str:
rel = os.path.relpath(str(cassette_path))
abs_path = os.path.abspath(str(cassette_path))

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.

P2 Consistent with using realpath for _REPO_ROOT, abs_path should also be resolved through any symlinks before computing the relative path, otherwise the prefix comparison can still fail when the cassette path arrives via a symlinked directory.

Suggested change
abs_path = os.path.abspath(str(cassette_path))
abs_path = os.path.realpath(str(cassette_path))

Comment on lines +30 to +31
except ValueError:
rel = os.path.basename(abs_path)

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.

P2 The ValueError fallback (Windows cross-drive paths) uses only os.path.basename, which drops all directory context. Two cassettes in different subdirectories that share the same filename — e.g. tests/a/test_foo.yaml and tests/b/test_foo.yaml — would both resolve to litellm:vcr:cassette:test_foo and silently share the same Redis entry. Using a short hash of the full absolute path as the fallback would avoid this collision while remaining stable.

Suggested change
except ValueError:
rel = os.path.basename(abs_path)
except ValueError:
import hashlib
rel = hashlib.sha1(abs_path.encode()).hexdigest()[:16]

@yuneng-berri
yuneng-berri merged commit 12c9a47 into litellm_internal_staging May 1, 2026
116 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_fix-redis-key-generation-d88e branch May 1, 2026 23:41
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
…eneration-d88e

Fix Redis key generation to be stable across working directories
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.

4 participants