Skip to content

make sdk-python fails on a Python 3.14 host, with an error that names nothing relevant #692

Open

Description

@yashksaini-coder

On a machine whose python3 is 3.14, make sdk-python fails in dependency resolution:

$ make sdk-python
python3 -m venv sdk/python/.venv
./sdk/python/.venv/bin/pip install -q -e './sdk/python[test,examples]'
  ...
  File ".../coincurve_.../hatch_build.py", line 34, in initialize
    raise RuntimeError(message)
  RuntimeError: Expected exactly one LICENSE file in cffi distribution, got 0
error: metadata-generation-failed
× Encountered error while generating package metadata.
╰─> coincurve
make: *** [Makefile:176: sdk-python] Error 1

Nothing in that output says "this Python is too new", which is what actually happened.

Cause

Two things combine:

  1. Makefile:175 is python3 -m venv sdk/python/.venv — the target pins no interpreter, so it
    takes whatever python3 is on PATH.

  2. sdk/python/pyproject.toml declares requires-python = ">=3.11", with no upper bound. But
    libp2p (py-libp2p) 0.8.0 pins coincurve==21.0.0:

    $ curl -s https://pypi.org/pypi/libp2p/0.8.0/json | jq -r '.info.requires_dist[]' | grep coincurve
    coincurve==21.0.0
    

    coincurve 21.0.0 (2025-03-08, still the latest on PyPI) publishes cp39–cp313 wheels only, and
    building its sdist raises the error above from coincurve/hatch_build.py:34.

So requires-python is wider than what can actually be installed: 3.14 satisfies the
declared floor and then fails deep inside a transitive dependency's build.

CI does not see this because every workflow pins python-version: "3.12"
(.github/workflows/sdk.yml:75, release.yml:118, member-journey.yaml:74). Only a developer
whose system python3 is 3.14 hits it, and the error does not tell them why.

The upstream half is tracked at
libp2p/py-libp2p#1140; it is blocked on
coincurve itself, so the ceiling is real for now rather than something agentmesh can resolve.

Suggested fix

Two small changes, both verified locally:

1. Declare the real ceiling in sdk/python/pyproject.toml:

requires-python = ">=3.11,<3.14"

The failure then names the actual constraint, on the path make sdk-python takes:

ERROR: Package 'agentmesh-p2p' requires a different Python: 3.14.7 not in '<3.14,>=3.11'

This also helps anyone installing the published agentmesh-p2p from PyPI, not just this
Makefile target. Worth a comment saying the bound is py-libp2p's and when to lift it.

Caveat I should flag: uv pip install -e does not enforce requires-python for an
editable local path — it resolves and still fails on the coincurve build. So this improves pip
(what the Makefile and pip install agentmesh-p2p use) but does not change the uv-editable
path.

2. Let the target's interpreter be overridden, matching the ?= convention already used
elsewhere in the Makefile (AGENTMESH_ONE_BIN, AGENTMESH_ONE_DATA_DIR):

PYTHON ?= python3
sdk-python:
	$(PYTHON) -m venv sdk/python/.venv

so a developer on 3.14 has a way forward:

$ make sdk-python PYTHON=python3.13
...
168 passed in 43.89s

I have both changes on a branch with the above output reproduced. I have not opened a PR yet
because I have not signed the Google CLA — happy to do that and send it if you would like the
patch, or to leave it with you if you would rather fix it differently.

Verified at cf1d27fa9bc6cc93dbe79cc99fa420d954f30ee9, CPython 3.14.7 / 3.13.15, Linux.

Activity

  1. asivanadi0 commented on Oct 13, 2026

    @asivanadi0
    Contributor

    You mentioned you already have a fix and are waiting on the CLA. Are you still planning to send it? If it would help, I have a version on asivanadi0:fix/sdk-python-version that sets requires-python = ">=3.11,<3.14" and has make sdk-python pick the newest supported interpreter with a clear error on 3.14. Happy to defer to yours.

  2. yashksaini-coder commented on Oct 14, 2026

    @yashksaini-coder
    Author

    Please send yours — it is better than what I have, and you are not blocked where I am.

    I fetched asivanadi0:fix/sdk-python-version and compared just the two files at issue.

    On pyproject.toml we wrote the same thing: requires-python = ">=3.11,<3.14" citing
    libp2p/py-libp2p#1140. Yours says it in two lines, mine took five.

    On the Makefile yours is the better design. Mine was only PYTHON ?= python3, which still
    requires the developer to know to override it — on a 3.14 host with no override it walks into
    the same coincurve error the issue is about. Yours probes for a supported interpreter and
    pre-flight-checks with a message that names what it found and how to override.

    I tested your logic on the host that prompted the issue (3.14.7, and no python3.11/12/13 on
    PATH at all), lifted into a scratch Makefile so the rest of your branch was not in the way:

    no supported interpreter on PATH falls back to python3, guard fires: sdk-python needs Python 3.11 to 3.13 ... python3 is Python 3.14.7. Install python3.13 or run: make sdk-python PYTHON=python3.13, exit 1
    python3.13 also on PATH selects python3.13 (3.13.15)
    explicit PYTHON=/path/to/python3.13 honoured

    All three are what you would want. Mine only gets the third one right.

    One small thing, if you want it. PYTHON ?= $(or $(firstword $(foreach p,...,$(shell ...))))
    is a recursively expanded variable, so the probes re-run on every $(PYTHON) expansion rather
    than once. I measured it by putting a counting shim on PATH as python3.12: your form probes
    each candidate 5 times per make run, against 1 for a simply expanded helper:

    SDK_PYTHON_AUTO := $(or $(firstword $(foreach p,python3.13 python3.12 python3.11 python3,$(shell $(p) -c '$(SDK_PYTHON_CHECK)' >/dev/null 2>&1 && echo $(p)))),python3)
    PYTHON ?= $(SDK_PYTHON_AUTO)

    With four candidates that is roughly 20 subprocess spawns instead of 4, and PYTHON= on the
    command line still wins. Same behaviour otherwise — all three rows above still hold with it.
    Entirely your call; it is a papercut, not a problem.

    I have not signed the Google CLA, so there is no reason to wait on me here. Happy to review
    your PR when it is up, and to retest it on the 3.14 host.

  3. added a commit that references this issue on Oct 14, 2026
    76933cd
  4. yashksaini-coder commented on Oct 19, 2026

    @yashksaini-coder
    Author

    Correcting my own recommendation in this issue, since #709 is now stuck on it and the
    suggestion was mine.

    I wrote above that the fix was to "declare the real ceiling" with
    requires-python = ">=3.11,<3.14". For a package that is already published that is wrong,
    and @aojea's pushback on #709 is right. requires-python is per-release metadata, but people
    install a package: capping only the newest release does not tell a 3.14 user "this does not
    support you", it tells the resolver "try an older one".

    agentmesh-p2p has 0.1.0, 0.1.0rc10 and 0.1.1 on PyPI, all >=3.11, all depending on
    libp2p>=0.8,<0.9. I checked what pip actually does with a cap, using a local index with two
    hand-built wheels:

    capdemo 0.1.0   Requires-Python: >=3.9
    capdemo 0.1.1   Requires-Python: >=3.9,<3.14      # what #709 proposes
    
    $ pip install capdemo          # CPython 3.14.8
    Name: capdemo
    Version: 0.1.0                 # silently took the older one, no error, no warning
    

    Then the same thing end to end on the real package, on 3.14.8:

    • today, uncapped: pip install agentmesh-p2p resolves 0.1.1 and fails loudly in coincurve's
      build (RuntimeError: Expected exactly one LICENSE file in cffi distribution, got 0);
    • capped: pip skips 0.1.1 and falls back to 0.1.0 — and pip install agentmesh-p2p==0.1.0
      on 3.14 fails with the identical coincurve error.

    So the cap costs a silent downgrade and buys nothing: the user ends up at the same cryptic
    message either way. It would only read correctly if every existing release were capped too, and
    nobody is proposing that.

    It is also worth being clear about whose constraint this is. libp2p 0.8.0 declares
    requires-python >=3.10,<4.0 while pinning coincurve==21.0.0, and coincurve 21.0.0 declares
    >=3.9 while publishing cp39-cp313 wheels only and shipping an sdist that does not build. The
    metadata that is actually wrong is two levels upstream; libp2p/py-libp2p#1140 tracks it. Agent
    Mesh restating it downstream does not make it true, and goes stale the moment coincurve ships
    3.14 wheels.

    What does hold up is the make sdk-python guard in #709: it involves no resolver, it is a
    developer-workflow check rather than published metadata, and it is the part that fixes the thing
    this issue actually reported — a confusing failure when building from the repo. @asivanadi0
    already offered on #709 to drop the pyproject cap and keep only that; that is the right shape,
    and the reason to do it is stronger than "upper bounds are discouraged".

    Sorry for sending #709 down this path to begin with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions