{"record":{"id":"381c41f1bdb39e3d","repo":"pandas-dev/pandas","slug":"extensionarray-fillna-does-not-support-filling-wit-381c41","errorCode":null,"errorMessage":"ExtensionArray.fillna does not support filling with a dict. Use Series.fillna instead.","messagePattern":"ExtensionArray\\.fillna does not support filling with a dict\\. Use Series\\.fillna instead\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/sparse/array.py","lineNumber":863,"sourceCode":"\n        Returns\n        -------\n        SparseArray\n\n        Notes\n        -----\n        When `value` is specified, the result's ``fill_value`` depends on\n        ``self.fill_value``. The goal is to maintain low-memory use.\n\n        If ``self.fill_value`` is NA, the result dtype will be\n        ``SparseDtype(self.dtype, fill_value=value)``. This will preserve\n        amount of memory used before and after filling.\n\n        When ``self.fill_value`` is not NA, the result dtype will be\n        ``self.dtype``. Again, this preserves the amount of memory used.\n        \"\"\"\n        if isinstance(value, dict):\n            raise TypeError(\n                \"ExtensionArray.fillna does not support filling with a dict. \"\n                \"Use Series.fillna instead.\"\n            )\n        if limit is not None:\n            raise ValueError(\"limit must be None\")\n        new_values = np.where(isna(self.sp_values), value, self.sp_values)\n\n        if self._null_fill_value:\n            # This is essentially just updating the dtype.\n            new_dtype = SparseDtype(self.dtype.subtype, fill_value=value)\n        else:\n            new_dtype = self.dtype\n\n        return self._simple_new(new_values, self._sparse_index, new_dtype)\n\n    def shift(self, periods: int = 1, fill_value=None) -> Self:\n        if not len(self) or periods == 0:\n            return self.copy()","sourceCodeStart":845,"sourceCodeEnd":881,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/sparse/array.py#L845-L881","documentation":"SparseArray.fillna rejects dict values because dict-based filling is defined only at the Series level (where labels map to fill values), not on the raw ExtensionArray which has no index. The guard explicitly redirects users to Series.fillna.","triggerScenarios":"Calling SparseArray.fillna({0: 1.0, 2: 3.0}) or arr.fillna(some_dict); also reached when code forwards a dict to an ExtensionArray.fillna generically.","commonSituations":"Reusing Series.fillna(value=dict) logic against the underlying .array or .values; refactoring a Series pipeline to operate on the ExtensionArray directly.","solutions":["Move the fillna to Series: pd.Series(arr, index=labels).fillna(dict_value).array.","If the dict maps positions to values, convert it to per-position logic and pass a scalar or array to fillna.","Map dict values onto a dense array first, then rebuild the SparseArray."],"exampleFix":"// before\narr.fillna({0: 9.0})  # raises\n// after\npd.Series(arr, index=[0, 1, 2]).fillna({0: 9.0}).array","handlingStrategy":"validation","validationCode":"def safe_fillna(arr, value=None, **kw):\n    if isinstance(value, dict):\n        return pd.Series(arr).fillna(value).array\n    return arr.fillna(value=value, **kw)","typeGuard":"def is_dict_fill(value) -> bool:\n    return isinstance(value, dict)","tryCatchPattern":"try:\n    arr.fillna(value)\nexcept TypeError as e:\n    if \"dict\" in str(e):\n        arr = pd.Series(arr).fillna(value).array\n    else:\n        raise","preventionTips":["Use Series.fillna for dict-based filling.","Validate value type before calling ExtensionArray.fillna.","Keep fillna logic at the Series level for sparse columns."],"tags":["sparse","fillna","dict","series-api"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}