{"record":{"id":"9fa6f413ca718079","repo":"pandas-dev/pandas","slug":"cannot-convert-na-to-integer","errorCode":null,"errorMessage":"cannot convert NA to integer","messagePattern":"cannot convert NA to integer","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/masked.py","lineNumber":805,"sourceCode":"        if isinstance(dtype, ExtensionDtype):\n            eacls = dtype.construct_array_type()\n            return eacls._from_sequence(self, dtype=dtype, copy=copy)\n\n        na_value: float | np.datetime64 | lib.NoDefault\n\n        # coerce\n        if dtype.kind == \"f\":\n            # In astype, we consider dtype=float to also mean na_value=np.nan\n            na_value = np.nan\n        elif dtype.kind == \"M\":\n            unit = np.datetime_data(dtype)[0]\n            na_value = np.datetime64(\"NaT\", unit)  # type: ignore[call-overload]\n        else:\n            na_value = lib.no_default\n\n        # to_numpy will also raise, but we get somewhat nicer exception messages here\n        if dtype.kind in \"iu\" and self._hasna:\n            raise ValueError(\"cannot convert NA to integer\")\n        if dtype.kind == \"b\" and self._hasna:\n            # careful: astype_nansafe converts np.nan to True\n            raise ValueError(\"cannot convert float NaN to bool\")\n\n        data = self.to_numpy(dtype=dtype, na_value=na_value, copy=copy)\n        return data\n\n    __array_priority__ = 1000  # higher than ndarray so ops dispatch to us\n\n    def __array__(\n        self, dtype: NpDtype | None = None, copy: bool | None = None\n    ) -> np.ndarray:\n        \"\"\"\n        the array interface, return my values\n        We return an object array here to preserve our scalar values\n        \"\"\"\n        if copy is False:\n            if not self._hasna:","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/masked.py#L787-L823","documentation":"Raised by BaseMaskedArray.astype when the target dtype has integer kind ('i','u') and the masked array contains missing values. Integer numpy dtypes have no native NA representation, so conversion would silently lose or wrap the NA; pandas raises a clearer message than letting to_numpy fail.","triggerScenarios":"Calling arr.astype('int64') or arr.astype(np.int32) on a nullable integer/float/boolean masked array where self._hasna is True.","commonSituations":"Forcing a nullable Int64 column back to numpy int64 without handling NAs; pipelines that assume no missing data; reads from Parquet/CSV that produced NA where downstream code expects plain ints.","solutions":["Cast to a nullable integer dtype instead: arr.astype('Int64').","Fill or drop NAs first: arr.fillna(0).astype('int64') or arr.dropna().astype('int64').","Cast to float to let NAs become np.nan: arr.astype('float64')."],"exampleFix":"// before\narr = pd.array([1, None, 3], dtype='Int64')\narr.astype('int64')   # raises\n// after\narr.fillna(0).astype('int64')","handlingStrategy":"validation","validationCode":"if dtype.kind in 'iu' and arr._hasna:\n    raise ValueError('Refusing int cast with NA; fill or drop first')\nout = arr.astype(dtype)","typeGuard":"def can_astype_int(arr) -> bool:\n    return not arr._hasna","tryCatchPattern":"try:\n    out = arr.astype('int64')\nexcept ValueError as e:\n    if 'NA to integer' in str(e):\n        out = arr.fillna(0).astype('int64')\n    else:\n        raise","preventionTips":["Check _hasna before casting to plain integer dtypes.","Keep NAs representable by using nullable Int dtypes through the pipeline.","Fill or drop NAs at a single, well-defined boundary before int casts."],"tags":["pandas","masked-array","astype","na-value","integer"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}