{"record":{"id":"2acfc0ae6e77c508","repo":"pandas-dev/pandas","slug":"default-empty-implementation-is-invalid-for-dtyp","errorCode":null,"errorMessage":"Default 'empty' implementation is invalid for dtype='{dtype}'","messagePattern":"Default 'empty' implementation is invalid for dtype='(.+?)'","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/base.py","lineNumber":2862,"sourceCode":"    @classmethod\n    def _empty(cls, shape: Shape, dtype: ExtensionDtype):\n        \"\"\"\n        Create an ExtensionArray with the given shape and dtype.\n\n        See also\n        --------\n        ExtensionDtype.empty\n            ExtensionDtype.empty is the 'official' public version of this API.\n        \"\"\"\n        # Implementer note: while ExtensionDtype.empty is the public way to\n        # call this method, it is still required to implement this `_empty`\n        # method as well (it is called internally in pandas)\n        obj = cls._from_sequence([], dtype=dtype)\n\n        taker = np.broadcast_to(np.intp(-1), shape)\n        result = obj.take(taker, allow_fill=True)\n        if not isinstance(result, cls) or dtype != result.dtype:\n            raise NotImplementedError(\n                f\"Default 'empty' implementation is invalid for dtype='{dtype}'\"\n            )\n        return result\n\n    def _quantile(self, qs: npt.NDArray[np.float64], interpolation: str) -> Self:\n        \"\"\"\n        Compute the quantiles of self for each quantile in `qs`.\n\n        Parameters\n        ----------\n        qs : np.ndarray[float64]\n        interpolation: str\n\n        Returns\n        -------\n        same type as self\n        \"\"\"\n        mask = np.asarray(self.isna())","sourceCodeStart":2844,"sourceCodeEnd":2880,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/base.py#L2844-L2880","documentation":"ExtensionArray._empty (base.py:2862) constructs an empty array via _from_sequence + take(-1, allow_fill=True) and validates the round-trip preserves type and dtype; if it does not, it raises NotImplementedError. This guards internal callers (e.g. dtype.empty) from silently producing a wrong-typed array, and is primarily an ExtensionArray-author contract violation.","triggerScenarios":"Triggered when pandas internally calls ExtensionDtype.empty(shape, dtype) (which delegates to _empty) for an EA whose _from_sequence or take does not round-trip a sentinel correctly. Common during reshaping/groupby/concat on a custom EA.","commonSituations":"Third-party or custom ExtensionArray with a buggy _from_sequence or take(allow_fill=True) implementation; changes after a pandas upgrade tighten the round-trip check.","solutions":["Override _empty(cls, shape, dtype) in your ExtensionArray subclass to return a correctly-typed empty array.","Fix take(allow_fill=True) so a -1 indexer yields NA of the correct dtype.","Fix _from_sequence to return an instance of cls with the requested dtype.","Report to the third-party EA library if you are not the author."],"exampleFix":"# before: custom EA whose take() returns wrong type\n# raises 'Default empty implementation is invalid'\n\n# after\n@classmethod\ndef _empty(cls, shape, dtype):\n    obj = cls._from_sequence([], dtype=dtype)\n    taker = np.broadcast_to(np.intp(-1), shape)\n    return obj.take(taker, allow_fill=True)","handlingStrategy":"validation","validationCode":"def verify_empty_roundtrip(cls, dtype):\n    obj = cls._from_sequence([], dtype=dtype)\n    taker = __import__(\"numpy\").broadcast_to(__import__(\"numpy\").intp(-1), (3,))\n    result = obj.take(taker, allow_fill=True)\n    return isinstance(result, cls) and result.dtype == dtype","typeGuard":"def ea_roundtrips_empty(cls, dtype) -> bool:\n    try:\n        verify_empty_roundtrip(cls, dtype)\n        return True\n    except Exception:\n        return False","tryCatchPattern":"try:\n    arr = dtype.empty(shape, dtype)\nexcept NotImplementedError as e:\n    if \"empty\" in str(e):\n        # fall back to building element-wise\n        arr = dtype.construct_array_type()._from_sequence([dtype.na_value] * int(__import__(\"numpy\").prod(shape)))\n    else:\n        raise","preventionTips":["Override _empty on custom EAs","Test take(allow_fill=True) round-trip in EA test suite","Ensure _from_sequence preserves dtype"],"tags":["extension-array","empty","subclass","internal","round-trip"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}