Main Ecosystems
HomePython CorePandas ReferenceNumPy ScientificFastAPI & PydanticDjango Enterprise
More Ecosystems
Environment & SetupRequests & HTTPAsyncIO ConcurrencyObject-Oriented OOPPyTorch Deep LearningScikit-Learn MLFlask FrameworkWeb ScrapingDatabase & ORMDevOps & Docker

ValueError: object __array__ method not producing an array in NumPy

Verified FixPython 3.10+NumPy 1.24+Silo: numpy

Quick Fix / Solution Rapide

Ensure custom classes implementing __array__() return a valid np.ndarray instance rather than primitive scalars, strings, or uncoerced lists.

Root Cause Analysis

This error occurs when Python tries to coerce a custom object into a NumPy ndarray via the __array__ protocol, but the object's __array__ method returns a value that is not an instance of numpy.ndarray.

1. The NumPy __array__ Protocol Contract

NumPy provides the __array__ special method to allow third-party classes, custom data wrappers, and mathematical containers to seamlessly integrate with NumPy functions like np.asarray(), np.array(), and mathematical ufuncs. According to the NumPy protocol specification, any implementation of __array__(self, dtype=None, copy=None) must return an authentic np.ndarray.

2. Returning Primitive Types or Strings

A frequent bug occurs when developers return raw Python primitives such as a string, integer, dictionary, or raw list from __array__ assuming that NumPy will automatically convert the return value into an array. When np.asarray() receives a non-ndarray return value from __array__, it halts execution and raises ValueError: object __array__ method not producing an array.

3. Signature Mismatch with Dtype and Copy Arguments

In modern NumPy versions (especially NumPy 1.20+ and 2.0+), NumPy passes dtype and copy keyword arguments to the __array__ method. If the custom method fails to handle these arguments or returns an incompatible data type when dtype is requested, the protocol validation fails.

4. Wrapper Classes and Incomplete Delegation

When wrapping external libraries or building pandas/arrow compatible adapters, delegation bugs where the underlying wrapped buffer is None or uninitialized will cause __array__ to return None or a non-array sentinel, immediately triggering this exception.

Reproduction Code (MCVE)

Example: Bug Reproduction
import numpy as np

class CustomDataWrapper:
    def __array__(self, dtype=None, copy=None):
        # Bug: returning a string instead of an ndarray
        return 'invalid_string_return_value'

wrapper = CustomDataWrapper()
np.asarray(wrapper)

Solution 1: Return a Valid np.ndarray from __array__

Wrap internal sequences or buffers in np.asarray() inside the __array__ implementation, respecting optional dtype and copy parameters.

Example: Recommended Solution
import numpy as np

class ValidDataWrapper:
    def __init__(self, values):
        self.values = values

    def __array__(self, dtype=None, copy=None):
        return np.asarray(self.values, dtype=dtype)

wrapper = ValidDataWrapper([10, 20, 30, 40])
arr = np.asarray(wrapper)
print(f'Successfully converted: {arr}, type: {type(arr)}')

Solution 2: Provide an Explicit to_numpy() Conversion Method

Instead of relying solely on the implicit __array__ protocol, provide an explicit conversion method (to_numpy()) for controlled data transformations.

Example: Alternative Solution
import numpy as np

class DataContainer:
    def __init__(self, items):
        self.items = list(items)

    def to_numpy(self, dtype=None):
        return np.array(self.items, dtype=dtype)

container = DataContainer([1.5, 2.8, 3.9])
arr = container.to_numpy(dtype=np.float64)
print(f'Explicit conversion array: {arr}, dtype: {arr.dtype}')

A common mistake when implementing custom array containers is returning a standard Python list from __array__. While Python lists are sequences, NumPy requires an actual np.ndarray instance to be returned by __array__. Always wrap raw lists in np.asarray(self.data, dtype=dtype). Another critical edge case involves handling optional arguments: modern NumPy passes both dtype and copy keyword arguments. If your method signature is defined as def __array__(self): without *args or dtype=None, copy=None, calls from np.asarray(obj, dtype=float) will fail with a TypeError before even reaching array validation. Contrasting this error with TypeError: Cannot convert numpy.ndarray to numpy.ndarray, the ValueError specifically indicates that the protocol method was found and executed, but violated the strict type contract of the protocol return value.