fix(deps): relax core runtime dependency pins from exact == to ranges - #26157
Conversation
When litellm migrated from Poetry to uv (PR BerriAI#24905, v1.83.1), the core dependency specifications in pyproject.toml changed from Poetry bare-version strings (e.g. openai = "2.30.0") to PEP 621 exact pins (openai==2.24.0). Poetry bare-version strings are actually caret ranges (^X.Y.Z == >=X.Y.Z,<X+1), but PEP 621 == is exact. This means every downstream package that installs litellm as a library dependency is now forced to downgrade aiohttp, pydantic, openai, click, and 8 other common packages to exact old versions. Fix: restore range specifiers for the 12 core runtime dependencies. The optional extras (proxy, proxy-runtime, etc.) are consumed primarily by Docker images where exact pins are appropriate and are left unchanged. The uv.lock file continues to provide exact reproducibility for Docker builds and CI. Fixes: BerriAI#26154
Greptile SummaryThis PR relaxes 12 core runtime dependency pins in
Confidence Score: 4/5Safe to merge after addressing the openai floor — the P1 concern is low-probability in practice but could cause silent runtime failures for unlucky downstream consumers. One P1 finding: the openai>=2.0.0 lower bound is significantly below the tested 2.24.0, which could allow installation of incompatible older openai v2 releases. The importlib-metadata floor concern is P2. All other changes are sound and the uv.lock continues to pin exact versions for CI/Docker. pyproject.toml — specifically the openai and importlib-metadata lower bounds
|
| Filename | Overview |
|---|---|
| pyproject.toml | Core runtime dependencies relaxed from exact == pins to lower-bounded ranges; openai floor (2.0.0) and importlib-metadata floor (6.0.0) are significantly below tested versions, risking silent runtime failures for downstream users who resolve older minor releases |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[litellm pyproject.toml] --> B{Install context}
B -->|Library consumer pip install litellm| C[Uses relaxed ranges\nhttpx>=0.28.0\nopenai>=2.0.0\npydantic>=2.5.0 less than 3.0.0\netc.]
B -->|Docker / CI via uv sync| D[Uses exact pins from uv.lock]
B -->|Proxy extras| E[Uses exact pins\ngunicorn==23.0.0\nfastapi==0.124.4\netc.]
C --> F{Resolver picks version}
F -->|Picks latest compatible| G[Works as expected]
F -->|Picks floor e.g. openai 2.0.0| H[Possible runtime error\nAPIs added after 2.0 missing]
D --> I[Reproducible build]
E --> J[Reproducible build]
Reviews (1): Last reviewed commit: "fix(deps): relax core runtime dependency..." | Re-trigger Greptile
| dependencies = [ | ||
| "fastuuid>=0.14.0", | ||
| "httpx>=0.28.0", | ||
| "openai>=2.0.0", |
There was a problem hiding this comment.
openai>=2.0.0 floor may be too permissive
The tested/released version was openai==2.24.0, but the floor is dropped 24 minor versions to 2.0.0. The OpenAI Python SDK has added new APIs, models, and response fields across 2.x minor releases that litellm almost certainly relies on. A downstream user whose resolver picks openai==2.1.0 could get AttributeError or ImportError at runtime with no warning at install time. Consider a tighter floor — e.g. openai>=2.20.0 — or document the actual minimum tested version to prevent silent breakage.
| "openai>=2.0.0", | ||
| "python-dotenv>=1.0.0", | ||
| "tiktoken>=0.7.0", | ||
| "importlib-metadata>=6.0.0", |
There was a problem hiding this comment.
importlib-metadata floor drops two major versions
The tested pin was 8.5.0; the new floor is 6.0.0. importlib-metadata had several API removals between major versions (the packages_distributions() API, deprecation of requires(), etc.). Dropping the floor two majors below the tested version may silently allow installs that fail at runtime on older 6.x or 7.x releases. A more conservative floor like >=8.0.0 would still dramatically relax downstream pressure while staying within the tested major series.
| ] | ||
| dependencies = [ | ||
| "fastuuid>=0.14.0", | ||
| "httpx>=0.28.0", |
There was a problem hiding this comment.
httpx has no upper bound on a pre-1.0 package
httpx is still pre-1.0 and has a history of breaking API changes across minor releases (streaming interface, timeout semantics, etc.). With httpx>=0.28.0 and no ceiling, litellm will accept future httpx 0.29, 0.30, or even 1.0 without any resolver warning. Adding an upper bound like <1.0 would guard against the inevitable 1.0 API break while still solving the downstream pinning problem.
| "httpx>=0.28.0", | |
| "httpx>=0.28.0,<1.0", |
baa50db
into
BerriAI:litellm_oss_staging_04_21_2026
The 12 core `[project.dependencies]` entries in pyproject.toml were exact `==` pins, a side effect of the Poetry → uv migration. This forces every downstream package that lists litellm as a dependency to downgrade common runtime libraries (openai, pydantic, aiohttp, click, jsonschema, ...) to the exact versions we ship. Customers have flagged this as a coexistence blocker. Switch to lower-bounded ranges with upper bounds where the upstream package is pre-1.0 or has a known breaking-major-version policy. Reproducibility for our Docker proxy and CI continues to come from `uv.lock`, which is regenerated here as a metadata-only diff (no resolved versions or hashes change). Inspired by #26157 (which got stranded on `litellm_oss_staging_04_21_2026` when the forward-merge to internal staging in #26216 was closed). Floors in this PR are tighter than #26157's: they were validated by installing litellm at `--resolution=lowest-direct` and importing the openai-namespace symbols the codebase actually uses. Floor highlights vs #26157: - openai >= 2.20 (was 2.0) — Responses API symbols + `Omit` need a 2.x mid-range floor - httpx >= 0.28, < 1.0 (was no upper) — pre-1.0 - importlib-metadata >= 8.0 (was 6.0) — stay in tested major - tokenizers >= 0.20, < 1.0 (was 0.19, no upper) — pre-1.0 - aiohttp >= 3.10, < 4.0 (was no upper) — bound major - pydantic >= 2.5, < 3.0 — kept - All other floors: keep tested major, add upper bound Adds a `check-dependency-floors.yml` GitHub Actions workflow that installs litellm at `--resolution=lowest-direct` on Python 3.10 and 3.13 and import-checks every openai symbol the codebase uses, so a future floor regression fails fast in CI rather than silently in the field.
The 12 core `[project.dependencies]` entries in pyproject.toml were exact `==` pins, a side effect of the Poetry → uv migration. This forces every downstream package that lists litellm as a dependency to downgrade common runtime libraries (openai, pydantic, aiohttp, click, jsonschema, ...) to the exact versions we ship. Customers have flagged this as a coexistence blocker. Switch to lower-bounded ranges with upper bounds where the upstream package is pre-1.0 or has a known breaking-major-version policy. Reproducibility for our Docker proxy and CI continues to come from `uv.lock`, which is regenerated here as a metadata-only diff (no resolved versions or hashes change). Inspired by BerriAI#26157 (which got stranded on `litellm_oss_staging_04_21_2026` when the forward-merge to internal staging in BerriAI#26216 was closed). Floors in this PR are tighter than BerriAI#26157's: they were validated by installing litellm at `--resolution=lowest-direct` and importing the openai-namespace symbols the codebase actually uses. Floor highlights vs BerriAI#26157: - openai >= 2.20 (was 2.0) — Responses API symbols + `Omit` need a 2.x mid-range floor - httpx >= 0.28, < 1.0 (was no upper) — pre-1.0 - importlib-metadata >= 8.0 (was 6.0) — stay in tested major - tokenizers >= 0.20, < 1.0 (was 0.19, no upper) — pre-1.0 - aiohttp >= 3.10, < 4.0 (was no upper) — bound major - pydantic >= 2.5, < 3.0 — kept - All other floors: keep tested major, add upper bound Adds a `check-dependency-floors.yml` GitHub Actions workflow that installs litellm at `--resolution=lowest-direct` on Python 3.10 and 3.13 and import-checks every openai symbol the codebase uses, so a future floor regression fails fast in CI rather than silently in the field.
Summary
When litellm migrated from Poetry to uv in PR #24905 (v1.83.1), a subtle semantic change broke library consumers:
openai = "2.30.0"are implicitly caret ranges — they resolve to>=2.30.0,<3.0.0openai==2.24.0is an exact pin — only that exact version is allowedThe migration converted Poetry's implicit ranges to PEP 621 exact pins, which forces every downstream package that lists
litellmas a dependency to downgrade 12 common runtime libraries (aiohttp, pydantic, openai, click, tokenizers, jinja2, etc.) to specific old patch versions — even if newer compatible versions are already installed.Fixes: #26154
Overlaps with: #25231 (which fixes only
python-dotenv)Changes
Only the 12 core
[project.dependencies]entries are changed — from exact==pins to lower-bounded ranges. The optional extras (proxy,proxy-runtime, etc.) keep their exact pins, since those are consumed by Docker images where reproducibility is important. Theuv.lockfile continues to provide exact pinning for Docker builds and CI.Before (exact pins — broken for downstream consumers):
After (lower-bounded ranges — compatible with downstream):
Why pydantic has an upper bound
pydantic>=2.5.0,<3.0.0— pydantic v3 would be a breaking API change. All other ranges are open-ended upward since those packages follow semver and breaking changes would be a major version bump.Testing
This is a metadata-only change to
pyproject.toml. Theuv.lockfile and CI continue to install the same exact versions for testing and Docker builds. No runtime behavior changes.