Skip to content

make sync fails on Python 3.14: the locked cffi 1.17.1 has no cp314 wheel, so the dev group needs a C compiler #4442

Closed

Description

@Chirag6722

pyproject.toml advertises Python 3.14 (Programming Language :: Python :: 3.14, line 26) and sets no upper bound on requires-python. On 3.14 the documented contributor setup does not complete.

What happens

From a clean checkout on Windows 11 with Python 3.14.7:

$ uv sync            # also fails as `uv sync --all-extras`, and as `make sync`
...
error: Failed to build `cffi==1.17.1`
  ... Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools"

hint: `cffi` (v1.17.1) was included because `openai-agents:dev` (v0.21.0)
      depends on `sounddevice` (v0.5.2) which depends on `cffi`

uv sync --python 3.12 succeeds immediately on the same checkout, which isolates it to the interpreter version rather than the machine.

Why

uv.lock pins cffi==1.17.1. That release publishes wheels for cp38–cp313 only:

cffi 1.17.1 wheel python tags: cp38, cp39, cp310, cp311, cp312, cp313
cp314 wheel present: False
latest cffi on PyPI:  2.1.1

So on 3.14 there is no wheel to install and uv falls back to building from the sdist, which needs a working C toolchain. On Windows that is MSVC Build Tools, which a contributor setting up a Python SDK has no other reason to have. cffi reaches the graph only through sounddevice, which is pulled by the dev group — so it is a hard requirement of the documented setup even for someone who will never touch the voice code.

Linux and macOS contributors on 3.14 are likely to hit the same resolution and survive it, because a C compiler is usually already present. The failure is therefore Windows-visible but not Windows-caused.

Why it is worth fixing rather than documenting

AGENTS.md tells a contributor to run make sync as step 3 of repo setup, and requires-python plus the 3.14 classifier tell them 3.14 is a supported interpreter. Someone who installs the newest stable Python — the reasonable default — hits a compiler error naming cffi, a package they did not ask for, in service of sounddevice, which they also did not ask for. Nothing in the error points back at the voice extra or suggests using an older interpreter.

Possible directions

Not proposing one, since the dependency policy is yours:

  1. Refresh the cffi pin in uv.lock. 2.1.1 publishes cp314 wheels.
  2. Move sounddevice out of dev and into the voice extra only, so the base contributor setup does not pull an audio stack.
  3. Cap requires-python (or drop the 3.14 classifier) until the dev graph installs cleanly on it, so the advertised support matches what setup does.

1 is the smallest and probably sufficient on its own. 2 is the one that stops this class of failure recurring, since it takes the whole native-audio dependency off the default contributor path.

Environment

Windows 11, Python 3.14.7 (uv-managed), uv 0.12.3, clean clone of main at 9aba900. Reproduces on uv sync, uv sync --all-extras, and make sync. uv sync --python 3.12 succeeds.

Activity

  1. samrusani commented on Aug 15, 2026

    @samrusani

    I will take this as a narrow lockfile fix: selectively refresh cffi in uv.lock so the development dependency graph includes CPython 3.14 wheels, without changing dependency groups or the supported Python metadata. I will verify the regenerated lock entries and run the repository required checks.

  2. Chirag6722 commented on Aug 15, 2026

    @Chirag6722
    ContributorAuthor

    Sounds right, and it is yours — I am not working on a fix, so no risk of duplicate PRs.

    Agree the narrow lockfile refresh is the right first move. One thing worth having while you are in there, since it decides whether this recurs: cffi reaches the graph only through sounddevice, which sits in the dev group rather than in the voice extra. So the base contributor setup pulls a native audio dependency even for someone who will never touch the voice code, and the next interpreter release puts you back here.

    That part is a dependency-grouping call rather than a lockfile one, so it is reasonable to leave out of a narrow fix — but if a maintainer would take it, moving sounddevice behind the extra is what stops the class rather than this instance.

    Happy to test the regenerated lock on Windows + 3.14 once you have a branch; that is the configuration the report came from, and uv sync --python 3.12 already succeeds there, so it is a clean before/after.

  3. Chirag6722 commented on Aug 16, 2026

    @Chirag6722
    ContributorAuthor

    One structural note for whoever lands the fix — this explains why CI could not have caught it, and it argues for the grouping change over the lockfile refresh alone.

    tests-windows in .github/workflows/tests.yml pins python-version: "3.13" and runs uv sync --all-extras --all-packages --group dev. The Linux matrix covers 3.10 through 3.14. So the only lane that installs the dev group on Windows is fixed at 3.13 — the last version for which cffi 1.17.1 publishes a wheel.

    That is exactly the seam the failure sits in:

    3.13 3.14
    Linux wheel or a C toolchain is present a C toolchain is present
    Windows wheel exists — CI is green here no wheel, no toolchain — untested

    So the matrix is not blind by accident; it is one version short of the combination that breaks. Refreshing the cffi pin fixes today's instance, but the next interpreter release reopens it in a lane CI still will not exercise.

    Two things that would close it for good, neither of which is a lockfile edit:

    1. Move sounddevice out of dev and behind the voice extra, so the default contributor setup carries no native audio dependency.
    2. Add 3.14 to tests-windows, or at least a uv sync --group dev smoke on the newest supported interpreter, so "supported Python metadata" and "the setup actually installs" cannot drift apart again.

    For the record, uv.lock on origin/main still reads cffi 1.17.1 as of this comment, so the instance is still live even though this issue is closed. Happy to verify a branch on Windows + 3.14 — that is the configuration the report came from.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions