pandas-dev/pandas · error · TypeError

Invalid value '{item}' for dtype 'str'. Value should be a st

Error message

Invalid value '{item}' for dtype 'str'. Value should be a string or missing value, got '{type(item).__name__}' instead.

What it means

Raised by ArrowStringArray.insert() when the item to insert is neither a str instance nor the missing sentinel libmissing.NA. The string[pyarrow] dtype is strictly typed, so inserting an int, float, None (vs NA), or any non-string scalar is rejected at the boundary rather than silently coerced. Callers must explicitly convert or filter non-string values.

Source

Thrown at pandas/core/arrays/string_arrow.py:309

    @classmethod
    def _from_sequence_of_strings(
        cls, strings, *, dtype: ExtensionDtype, copy: bool = False
    ) -> Self:
        return cls._from_sequence(strings, dtype=dtype, copy=copy)

    @property
    def dtype(self) -> StringDtype:  # type: ignore[override]
        """
        An instance of 'string[pyarrow]'.
        """
        return self._dtype

    def insert(self, loc: int, item) -> ArrowStringArray:
        if self.dtype.na_value is np.nan and item is np.nan:
            item = libmissing.NA
        if not isinstance(item, str) and item is not libmissing.NA:
            raise TypeError(
                f"Invalid value '{item}' for dtype 'str'. Value should be a "
                f"string or missing value, got '{type(item).__name__}' instead."
            )
        return super().insert(loc, item)

    def _convert_bool_result(self, values, na=lib.no_default, method_name=None):
        validate_na_arg(na, name="na")
        if self.dtype.na_value is np.nan:
            if na is lib.no_default or isna(na):
                # NaN propagates as False
                values = values.fill_null(False)
            else:
                values = values.fill_null(na)
            return values.to_numpy()
        elif na is not lib.no_default and not isna(na):  # pyright: ignore [reportGeneralTypeIssues]
            values = values.fill_null(na)
        return BooleanDtype().__from_arrow__(values)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Convert the item to str before inserting: `arr.insert(loc, str(item))`.
  2. Use `pd.NA` (the string dtype's missing value) instead of `None` to represent missingness.
  3. Filter or coerce upstream so the insert site only ever sees str/pd.NA.
  4. If you genuinely need mixed types, use dtype=object instead of 'string[pyarrow]'.

Example fix

# before
arr.insert(0, 42)  # TypeError
# after
arr.insert(0, str(42))
# or for missing:
arr.insert(0, pd.NA)
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd
from pandas._libs import missing as libmissing

def safe_insert(arr, loc, item):
    if item is not libmissing.NA and not isinstance(item, str):
        item = str(item)
    return arr.insert(loc, item)

Type guard

from pandas._libs import missing as libmissing
import numpy as np
def is_valid_string_item(item) -> bool:
    return isinstance(item, str) or item is libmissing.NA or item is pd.NA

Try / catch

try:
    arr.insert(loc, item)
except TypeError as e:
    if 'Invalid value' in str(e) and 'dtype' in str(e):
        arr.insert(loc, str(item))
    else:
        raise

Prevention

When it happens

Trigger: Calling `arr.insert(loc, 5)`, `arr.insert(loc, None)`, or `arr.insert(loc, 3.14)` on an ArrowStringArray. The guard at string_arrow.py:308 checks `not isinstance(item, str) and item is not libmissing.NA`.

Common situations: Building mixed-type columns dynamically; reading user input that was not sanitized to strings; confusing None (Python null) with pandas NA; passing a numpy.str_ that is actually fine but a numpy int that is not.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/099ff22eaa53b4fb. Report an issue: GitHub.