NumPy 2 breaking changes: same code on 1.26 vs 2.x (tested)

The NumPy 2 changes that break most code: scalar repr is now np.float64(1.5), Python scalars no longer upcast (np.uint8(200) + 100 = 44), copy=False raises, and aliases like np.float_, np.NaN, np.in1d are gone.

One script, run unchanged under NumPy 1.26.4 (Python 3.11.17) and NumPy 2.5.4 (Python 3.13.5), shows the changes that break most code after upgrading. Each row prints the result, the exception, or the warning raised.

1. The same code on NumPy 1.26 and NumPy 2

import numpy as np
print("numpy", np.__version__)
checks = {
    "repr(np.float64(1.5))": lambda: repr(np.float64(1.5)),
    "np.float32(3) + 3.0 -> dtype": lambda: (np.float32(3) + 3.0).dtype,
    "np.uint8(200) + 100": lambda: np.uint8(200) + 100,
    "np.array([1, 2], copy=False) on a list": lambda: np.array([1, 2], copy=False),
    "np.float_": lambda: np.float_,
    "np.NaN": lambda: np.NaN,
    "np.in1d([1], [1])": lambda: np.in1d([1], [1]),
    "np.row_stack([[1], [2]]).shape": lambda: np.row_stack([[1], [2]]).shape,
}
import warnings
warnings.simplefilter("always")
for k, f in checks.items():
    with warnings.catch_warnings(record=True) as w:
        try:
            r = f()
        except Exception as e:
            r = f"{type(e).__name__}: {str(e).splitlines()[0][:90]}"
    extra = f"  [{w[0].category.__name__}]" if w else ""
    print(f"{k:42} {r}{extra}")

NumPy 1.26.4:

numpy 1.26.4
repr(np.float64(1.5))                      1.5
np.float32(3) + 3.0 -> dtype               float64
np.uint8(200) + 100                        300
np.array([1, 2], copy=False) on a list     [1 2]
np.float_                                  <class 'numpy.float64'>
np.NaN                                     nan
np.in1d([1], [1])                          [ True]
np.row_stack([[1], [2]]).shape             (2, 1)

NumPy 2.5.4:

numpy 2.5.4
repr(np.float64(1.5))                      np.float64(1.5)
np.float32(3) + 3.0 -> dtype               float32
np.uint8(200) + 100                        44  [RuntimeWarning]
np.array([1, 2], copy=False) on a list     ValueError: Unable to avoid copy while creating an array as requested.
np.float_                                  AttributeError: `np.float_` was removed in the NumPy 2.0 release. Use `np.float64` instead.
np.NaN                                     AttributeError: `np.NaN` was removed in the NumPy 2.0 release. Use `np.nan` instead.
np.in1d([1], [1])                          AttributeError: module 'numpy' has no attribute 'in1d'
np.row_stack([[1], [2]]).shape             AttributeError: module 'numpy' has no attribute 'row_stack'

2. What changed, row by row

3. Fixes that work on NumPy 2

import numpy as np
print("numpy", np.__version__)
x = np.float64(1.5)
print("repr:", repr(x), "| float():", float(x), "| str():", str(x))
np.set_printoptions(legacy="1.25")
print("legacy='1.25' repr:", repr(x))
np.set_printoptions(legacy=False)

print("np.asarray([1, 2]):", np.asarray([1, 2]))
print("np.isin([1, 3], [1]):", np.isin([1, 3], [1]))
print("np.vstack([[1], [2]]).shape:", np.vstack([[1], [2]]).shape)
print("np.uint8(200) + np.int64(100):", np.uint8(200) + np.int64(100))
print("np.float32(3) + np.float64(3.0) dtype:", (np.float32(3) + np.float64(3.0)).dtype)

Output:

numpy 2.5.4
repr: np.float64(1.5) | float(): 1.5 | str(): 1.5
legacy='1.25' repr: 1.5
np.asarray([1, 2]): [1 2]
np.isin([1, 3], [1]): [ True False]
np.vstack([[1], [2]]).shape: (2, 1)
np.uint8(200) + np.int64(100): 300
np.float32(3) + np.float64(3.0) dtype: float64

Use float(x) / x.item() when you need plain Python values, or np.set_printoptions(legacy="1.25") to get the old repr while you migrate. Replace np.array(x, copy=False) with np.asarray(x), np.in1d with np.isin, np.row_stack with np.vstack. For promotion, make the other operand a NumPy scalar or array of the dtype you want (np.int64(100)) or cast first.

4. Import errors after upgrading

If the failure happens at import, it is a compiled package built for NumPy 1.x, not your code: numpy.dtype size changed, may indicate binary incompatibility and AttributeError: _ARRAY_API not found.

Related: numpy errstate, Object of type int64 is not JSON serializable, pandas 3 breaking changes.

If pip install of an old pinned numpy fails with metadata-generation-failed, see numpy error: metadata-generation-failed. If import tensorflow fails with _ARRAY_API not found, see TensorFlow import error with NumPy 2. The general banner, A module that was compiled using NumPy 1.x cannot be run in NumPy 2, is explained in this guide. With OpenCV: numpy.core.multiarray failed to import. With scikit-learn/SciPy: import sklearn _ARRAY_API not found. Which SciPy versions allow NumPy 2: SciPy NumPy 2 compatibility. Matplotlib: first version that works with NumPy 2. Numba: Numba needs NumPy 2.2 or less. PyArrow: PyArrow NumPy 2.0 compatibility. statsmodels: statsmodels NumPy 2 compatibility (plus the SciPy _lazywhere and pandas 3 errors). gensim: cannot import name triu from scipy.linalg, and NumPy 2. shap: shap NumPy 2 compatibility. spaCy: spaCy NumPy 2 compatibility. PyTables: PyTables NumPy 2 compatibility. astropy: astropy NumPy 2 compatibility (and the NumPy 2.4 in1d removal). NumPy 2.4 removals: no attribute in1d / trapz. scikit-learn-extra: scikit-learn-extra NumPy 2 (dtype size changed). librosa: librosa NumPy 2 compatibility (works; old versions hit pkg_resources).

Frequently asked questions

Why does NumPy 2 print np.float64(1.5) instead of 1.5?

NumPy 2 changed scalar repr. str()/print are unchanged; use float(x), or np.set_printoptions(legacy='1.25') temporarily.

Why does np.array(x, copy=False) raise ValueError in NumPy 2?

copy=False now means never copy. Use np.asarray(x) to copy only when needed.

Why does np.uint8(200) + 100 give 44 in NumPy 2?

NEP 50: the Python int no longer upcasts the uint8, so the result overflows and wraps (with a RuntimeWarning). NumPy 1.26 gave 300.

Written with AI assistance. Measured on 2026-10-23: NumPy 1.26.4 on Python 3.11.17 and NumPy 2.5.4 on Python 3.13.5, same script. Each block was run verbatim and the output pasted unedited. PlainTables is our extension; Python and NumPy are free.