{"record":{"id":"34bd50949c1fe8bd","repo":"pandas-dev/pandas","slug":"this-method-must-be-defined-in-the-concrete-class","errorCode":null,"errorMessage":"This method must be defined in the concrete class {name}","messagePattern":"This method must be defined in the concrete class (.+?)","errorType":"exception","errorClass":"AbstractMethodError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/_mixins.py","lineNumber":114,"sourceCode":"    \"\"\"\n\n    _ndarray: np.ndarray\n\n    # scalar used to denote NA value inside our self._ndarray, e.g. -1\n    #  for Categorical, iNaT for Period. Outside of object dtype,\n    #  self.isna() should be exactly locations in self._ndarray with\n    #  _internal_fill_value.\n    _internal_fill_value: Any\n\n    def _box_func(self, x):\n        \"\"\"\n        Wrap numpy type in our dtype.type if necessary.\n        \"\"\"\n        return x\n\n    def _validate_scalar(self, value):\n        # used by NDArrayBackedExtensionIndex.insert\n        raise AbstractMethodError(self)\n\n    # ------------------------------------------------------------------------\n\n    @overload\n    def view(self, dtype: None = ...) -> Self: ...\n\n    @overload\n    def view(self, dtype: Dtype | None = ...) -> ArrayLike: ...\n\n    def view(self, dtype: Dtype | None = None) -> ArrayLike:\n        # We handle datetime64, datetime64tz, timedelta64, and period\n        #  dtypes here. Everything else we pass through to the underlying\n        #  ndarray.\n        if dtype is None or dtype is self.dtype:\n            return self._from_backing_data(self._ndarray)\n\n        if isinstance(dtype, type):\n            # we sometimes pass non-dtype objects, e.g np.ndarray;","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/_mixins.py#L96-L132","documentation":"`AbstractMethodError` raised by the default `_validate_scalar` on `NDArrayBackedExtensionArray` (in `pandas/core/arrays/_mixins.py`). The message is the standard `AbstractMethodError` text ('This method must be defined in the concrete class {name}'). It signals that a concrete subclass forgot to override `_validate_scalar`, which pandas calls (e.g. via `NDArrayBackedExtensionIndex.insert`) to coerce an arbitrary Python value into the array's scalar type.","triggerScenarios":"Subclassing `NDArrayBackedExtensionArray` (or `ExtensionArray`) without implementing `_validate_scalar`, then performing an operation that needs scalar validation: `Index.insert`, `append` with a scalar, `fillna`, or `_validate_setitem_value` paths that delegate to it. Calling `arr._validate_scalar(value)` directly also triggers it.","commonSituations":"Writing a third-party ExtensionArray backed by a numpy ndarray and forgetting this hook; upgrading pandas and hitting a code path that newly calls `_validate_scalar`; copy-pasting an EA skeleton from an outdated tutorial.","solutions":["Implement `_validate_scalar(self, value)` on the concrete subclass to convert/validate a scalar and return the dtype's native scalar (raise TypeError/ValueError on invalid input).","Mirror an existing implementation, e.g. `pandas/core/arrays/integer.py` `_validate_scalar`, for the expected shape.","If you did not mean to subclass, use a built-in dtype (IntegerArray, StringDtype, ArrowDtype) instead of a custom EA."],"exampleFix":"// before\nclass MyArray(NDArrayBackedExtensionArray):\n    _dtype = MyDtype()\n    # _validate_scalar inherited -> AbstractMethodError on insert\n\n// after\nclass MyArray(NDArrayBackedExtensionArray):\n    _dtype = MyDtype()\n    def _validate_scalar(self, value):\n        if isinstance(value, self._dtype.type) or value is pd.NaT:\n            return value\n        raise TypeError(f'Invalid scalar {value!r} for {self.dtype}')","handlingStrategy":"type-guard","validationCode":"import inspect\nif not getattr(type(arr)._validate_scalar, '__isabstractmethod__', False) is False and 'AbstractMethodError' in inspect.getsource(type(arr)._validate_scalar):\n    raise TypeError(f'{type(arr).__name__} does not implement _validate_scalar')","typeGuard":"def implements_validate_scalar(arr) -> bool:\n    import inspect\n    src = inspect.getsource(type(arr)._validate_scalar)\n    return 'AbstractMethodError' not in src","tryCatchPattern":"from pandas.errors import AbstractMethodError\ntry:\n    arr._validate_scalar(v)\nexcept AbstractMethodError as e:\n    raise NotImplementedError(f'Custom EA {type(arr).__name__} must implement _validate_scalar') from e","preventionTips":["When subclassing NDArrayBackedExtensionArray, copy the full method list from an existing concrete array (integer.py, datetimes.py)","Add a unit test that calls _validate_scalar on a representative scalar","Register an abc.ABCMeta abstractmethod so the failure happens at class definition, not runtime"],"tags":["extension-array","subclassing","abstract-method","internals"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}