Skip to content

BLD: exclude numpy 2.5.0 when building wheels (py3.14 segfault)#66090

Merged
jbrockmendel merged 2 commits into
pandas-dev:mainfrom
jbrockmendel:bug-66086
Jul 13, 2026
Merged

BLD: exclude numpy 2.5.0 when building wheels (py3.14 segfault)#66090
jbrockmendel merged 2 commits into
pandas-dev:mainfrom
jbrockmendel:bug-66086

Conversation

@jbrockmendel

@jbrockmendel jbrockmendel commented Jun 29, 2026

Copy link
Copy Markdown
Member

closes #66083
closes #66085
closes #66086
closes #66089
closes #66104

Summary

The 3.0.4 wheels segfault constructing a Timedelta (and on other datetime paths) on Python 3.14 + numpy 2.3.x/2.4.x. This is not a pandas source bug — timedeltas.pyx / util.pxd / meson.build are byte-identical to 3.0.3.

The 3.0.4 wheels were built against numpy 2.5.0, and a wheel built against numpy 2.5.0 is not backward-compatible with older numpy — it segfaults at runtime on numpy 2.3.x/2.4.x. This is numpy's documented forward- but not backward-compatible ABI (numpy 2.5's header reorganization for opaque builds made it bite). Independently reproduced by @Alvaro-Kothe, and discussed upstream in numpy/numpy#31804. The fix is the standard one: build the wheels against the oldest supported numpy.

Isolation (linux x86_64, py3.14)

2×2 of build numpy × build Cython, each run on numpy 2.5.0 / 2.4.6 / 2.3.3:

built against run @ 2.5.0 run @ 2.4.6 run @ 2.3.3
numpy 2.5.0 + Cython 3.3.0a1 💥 SIGSEGV 💥 SIGSEGV
numpy 2.5.0 + Cython 3.2.6 💥 SIGSEGV 💥 SIGSEGV
numpy 2.3.3 + Cython 3.3.0a1
numpy 2.3.3 + Cython 3.2.6

The crash tracks the build numpy only — the Cython version is irrelevant. (Reproduced fault offsets match the reports exactly: _multiarray_umath …+0x101f18, …+0xd5f58.)

Changes (pyproject.toml)

  • Build numpy >=2.0.0==2.3.3: build against the oldest numpy with wheels for every supported Python/platform (cp314 + win_arm64), instead of the newest. Building against the oldest supported numpy keeps wheels compatible with every numpy ≥ the runtime floor (and with numpy 1.26+).
  • Test numpy — pin the cibuildwheel test step to the oldest supported numpy, so a build-vs-runtime ABI mismatch like this is caught in CI instead of shipping. Previously each wheel was only ever tested against the same numpy it was built with, which is why this slipped through green.

Notes

  • Needs backporting to 3.0.x for a 3.0.5 release (3.0.4 is the broken release); a v3.0.5 whatsnew entry should be added on the backport.
  • Linux and Windows both reproduce the crash (BUG: date_range crashes python process #66104 is a real-world Windows hit on cp313 + numpy 2.4.6); macOS does not, even with the broken toolchain. The build pin applies to all platforms regardless.

🤖 Generated with Claude Code

@jorisvandenbossche

Copy link
Copy Markdown
Member

The cp31x 3.0.4 wheels were built against numpy 2.5.0 and Cython 3.3.0a1 (an alpha). numpy's C-ABI is forward- but not backward-compatible, so a binary built against a newer numpy crashes on an older one.

That is not true AFAIK. Since numpy 2.0 we don't have to do this pinning anymore. If this is actually what is happening, that sounds as a bug in numpy we should report.

@jbrockmendel jbrockmendel changed the title BLD: fix Python 3.14 wheel segfault (numpy ABI / Cython alpha) BLD: don't build wheels against numpy 2.5.0 (py3.14 segfault regression) Jun 29, 2026
@Alvaro-Kothe

Copy link
Copy Markdown
Member

I think the issue is indeed backward incompatibility. I did manage to reproduce by compiling pandas against Numpy 2.5.0 and after downgrading Numpy I got the segfault.

From the Numpy docs:

NumPy’s ABI is forward compatible but not backward compatible. This means that binaries compiled against an older version of NumPy will still work with newer versions, but binaries compiled against a newer version will not necessarily work with older ones.

I think the solution is to build the wheels against the minimum supported version of NumPy?

@mroeschke

Copy link
Copy Markdown
Member

numpy/numpy#31804 was opened in NumPy to discuss the ABI break and it sounds like we'll need to pin NumPy when building

@jbrockmendel jbrockmendel changed the title BLD: don't build wheels against numpy 2.5.0 (py3.14 segfault regression) BLD: build wheels against the oldest supported numpy (py3.14 segfault) Jun 30, 2026
@seberg

seberg commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Sorry, repeating here, but you shouldn't have to do this, if you do then something is very wrong.

It sounded like the whole problem here is making sure that ndarraytypes.h is included after whatever defines PY_ARRAY_UNIQUE_SYMBOL. There is no ABI break as such.

@mroeschke

mroeschke commented Jun 30, 2026

Copy link
Copy Markdown
Member

So for context, I believe the yanked 3.0.4 wheels were built from this job: https://github.com/pandas-dev/pandas/actions/runs/28315212942

From skimming some build logs:

  • cython-3.3.0a1 was generally used (+1 for this PR avoiding alphas)
  • Python 3.11 wheels were built with numpy-2.4.6 (makes sense as NumPy 2.5 dropped support for 3.11)
  • Python 3.12+ wheels were built with numpy-2.5.0

@mroeschke

Copy link
Copy Markdown
Member

I was able to get an agent to find a plausible NumPy bug that caused the segfault numpy/numpy#31814

@seberg

seberg commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Thanks @mroeschke, I would suggest you just blocklist specifically NumPy 2.5.0 for compilation (I dunno how nice that is).

This is clearly a bug in NumPy's .pxd file and Matthew's agent didn't get it right, but did point at the right direction at least.
EDIT: And I also got it slightly wrong, because I seriously didn't expect that we don't have a non-underscored version for this public API.

(All that said, I could see forcing the identical NumPy version for all bug-fix releases, but as annoying as this, I am not sure it's worth the logistics.)

@jorisvandenbossche

Copy link
Copy Markdown
Member

@jbrockmendel can you update this based on the comments?

@jbrockmendel

Copy link
Copy Markdown
Member Author

It isn't clear to me there is a consensus on what to update.

@seberg

seberg commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Honestly, @charris was so nice and did the 2.5.1 yesterday which should fix this. So you should be able to just do nothing in practice.

@jorisvandenbossche

Copy link
Copy Markdown
Member

It isn't clear to me there is a consensus on what to update.

My read is: keep the change to avoid cython pre-releases (as Matt also +1ed above, and in general there is no reason to build with pre-releases), and for numpy specifically disallow just 2.5.0 (as Sebastian said, although with the new numpy release that might not be needed, but would maybe still do it)

@jorisvandenbossche

Copy link
Copy Markdown
Member

@jbrockmendel can you also update the PR title and reduce the verbosity of the comments a bit?

And you could keep the cython change?

@jbrockmendel jbrockmendel changed the title BLD: build wheels against the oldest supported numpy (py3.14 segfault) BLD: exclude numpy 2.5.0 when building wheels (py3.14 segfault) Jul 9, 2026
numpy 2.5.0 shipped a regression that made wheels built against it
segfault on older numpy (2.3.x/2.4.x) -- how the yanked 3.0.4 cp31x
wheels crashed for users on an older numpy (GH#66086; numpy GH#31804,
fixed in numpy 2.5.1). Exclude just numpy 2.5.0 from the build
environment (numpy>=2.0.0,!=2.5.0).

Also bound Cython <4 rather than <4.0.0a0: a pre-release in the bound
makes pip eligible to install Cython pre-releases, which is how the
3.3.0a1 alpha got pulled into the 3.0.4 wheels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mroeschke mroeschke added this to the 3.0.4 milestone Jul 13, 2026
@jbrockmendel jbrockmendel marked this pull request as ready for review July 13, 2026 20:28
@jbrockmendel jbrockmendel merged commit d671ee2 into pandas-dev:main Jul 13, 2026
49 checks passed
@jbrockmendel jbrockmendel deleted the bug-66086 branch July 13, 2026 20:28
@lumberbot-app

lumberbot-app Bot commented Jul 13, 2026

Copy link
Copy Markdown

Owee, I'm MrMeeseeks, Look at me.

There seem to be a conflict, please backport manually. Here are approximate instructions:

  1. Checkout backport branch and update it.
git checkout 3.0.x
git pull
  1. Cherry pick the first parent branch of the this PR on top of the older branch:
git cherry-pick -x -m1 d671ee2606c42eb0bde80ad44e73e3c1e9628829
  1. You will likely have some merge/cherry-pick conflict here, fix them and commit:
git commit -am 'Backport PR #66090: BLD: exclude numpy 2.5.0 when building wheels (py3.14 segfault)'
  1. Push to a named branch:
git push YOURFORK 3.0.x:auto-backport-of-pr-66090-on-3.0.x
  1. Create a PR against branch 3.0.x, I would have named this PR:

"Backport PR #66090 on branch 3.0.x (BLD: exclude numpy 2.5.0 when building wheels (py3.14 segfault))"

And apply the correct labels and milestones.

Congratulations — you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon!

Remember to remove the Still Needs Manual Backport label once the PR gets merged.

If these instructions are inaccurate, feel free to suggest an improvement.

jbrockmendel added a commit that referenced this pull request Jul 14, 2026
…lding wheels (py3.14 segfault)) (#66319)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment