Repository navigation
Description
Description
The PyPI check keeps one cache file (version_cache.json) with the latest version and whether the installed version is yanked.
get_latest_version_from_pypi trusts any cache younger than 24 hours that has a current_version key, whichever version wrote it.
is_current_version_yanked notices the cache was written for another version and calls get_latest_version_from_pypi to refresh it.
That call returns straight from the same cache, so nothing is fetched, and the old yanked flag is read back.
After upgrading from a yanked release, the console prints the red "Yanked Version" panel on every run for up to 24 hours.
It names the new version and shows the old release's reason.
Steps to Reproduce
- Run a yanked crewAI release once, so the cache holds
current_version_yanked: true. - Upgrade to a good release (
uv sync --upgrade-package crewai). - Run any crew or flow with the console output on.
Without installing anything, the same state:
import json, tempfile
from datetime import datetime
from pathlib import Path
from unittest.mock import patch, MagicMock
import crewai_core.version as v
cache = Path(tempfile.mkdtemp()) / "version_cache.json"
cache.write_text(json.dumps({
"version": "2.0.0", "timestamp": datetime.now().isoformat(),
"current_version": "1.0.0", "current_version_yanked": True,
"current_version_yanked_reason": "bad release"}))
releases = {"releases": {"1.0.0": [{"yanked": True, "yanked_reason": "bad release"}],
"2.0.0": [{"yanked": False}]}}
resp = MagicMock()
resp.__enter__.return_value.read.return_value = json.dumps(releases).encode()
with patch.object(v, "_get_cache_file", return_value=cache), \
patch.object(v, "get_crewai_version", return_value="2.0.0"), \
patch.object(v.request, "urlopen", return_value=resp) as urlopen:
print(v.is_current_version_yanked(), "urlopen calls:", urlopen.call_count)Expected behavior
2.0.0 is not yanked, so the result is (False, "").
The cache from 1.0.0 is not used, and PyPI is queried once to rewrite it.
Screenshots/Code snippets
Output on main:
(True, 'bad release') urlopen calls: 0
The panel comes from ConsoleFormatter (crewai/events/utils/console_formatter.py):
Version 2.0.0 has been yanked from PyPI.
Reason: bad release
To update, run: uv sync --upgrade-package crewai
Operating System
Windows 11
Python Version
3.13 (the form lists 3.10 to 3.12, nothing in the code depends on it)
crewAI Version
1.15.35 (main at 6bd60b2).
crewAI Tools Version
1.15.35
Virtual Environment
Venv (uv)
Evidence
Tests added on the fix branch, run against unfixed code:
FAILED test_version.py::TestVersionCacheAfterUpgrade::test_upgrading_from_a_yanked_version_clears_the_yanked_flag assert True is False
FAILED test_version.py::TestVersionCacheAfterUpgrade::test_cache_written_for_another_version_is_not_used_offline assert True is False
FAILED test_version.py::TestVersionCacheAfterUpgrade::test_latest_version_is_refetched_for_a_new_installed_version assert '2.0.0' == '3.0.0'
The existing test_triggers_fetch_on_stale_cache hides this: it mocks get_latest_version_from_pypi, so the cache short-circuit never runs.
Possible Solution
In get_latest_version_from_pypi, use the cache only when cache_data["current_version"] == get_crewai_version().
An upgrade then fetches once and rewrites the file.
In is_current_version_yanked, return (False, "") when the fetch failed and the cache still belongs to another version.
Additional context
The cache also drives the "update available" check, so it is read the same way there. The yanked panel is the visible symptom.
Searches run (no match for this bug):
gh issue list --state all --search "yanked version after upgrade","version_cache.json","is_current_version_yanked","yanked panel stale cache": no issues.gh pr listwith the same terms: only feat: add yanked detection for version notes #4464 (the original yank detection) and refactor: extract CLI into standalone crewai-cli package #4884 (CLI extraction).- Local grep of all issue and PR titles for
yank,version cache,pypi: no match. git log --since=60.daysoncrewai_core/version.py: only fix(cli): add the chosen provider's crewai extra to new projects #9029, unrelated.
Activity