pandas-dev/pandas · error · TypeError

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

Error message

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

What it means

Raised by ArrowStringArray._validate_setitem_value() when assigning a scalar that is not a str and not NA (after isna already handled NaN/NaT/None). This guards __setitem__ and similar assignment paths so a string[pyarrow] array cannot be corrupted by a non-string scalar. Unlike object dtype, no implicit coercion happens; the caller must convert explicitly.

Source

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

        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)

    def _validate_setitem_value(self, value):
        """Maybe convert value to be pyarrow compatible."""
        if is_scalar(value):
            if isna(value):
                value = None
            elif not isinstance(value, str):
                raise TypeError(
                    f"Invalid value '{value}' for dtype 'str'. Value should be a "
                    f"string or missing value, got '{type(value).__name__}' instead."
                )
        elif isinstance(value, type(self)):
            pass
        else:
            if not is_array_like_deprecate_non_pandas(value):
                value = np.asarray(value, dtype=object)
            else:
                value = np.asarray(value)
            if len(value) and not (
                value.ndim == 1 and lib.is_string_array(value, skipna=True)
            ):
                raise TypeError(
                    "Invalid value for dtype 'str'. Value should be a "
                    "string or missing value (or array of those)."
                )
        return super()._validate_setitem_value(value)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Wrap the assigned value in str(): `s.iloc[0] = str(value)`.
  2. Use pd.NA for missing assignments rather than 0, -1, or None.
  3. Coerce the source column to string before assignment: `s.iloc[0] = other.astype('string').iloc[0]`.
  4. If mixed scalar types are truly needed, declare the column as dtype=object.

Example fix

# before
s = pd.Series(['a','b'], dtype='string[pyarrow]')
s.iloc[0] = 100  # TypeError
# after
s.iloc[0] = str(100)
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd
from pandas.api.types import is_string_dtype

def safe_setitem_scalar(arr, loc, value):
    if pd.isna(value):
        value = pd.NA
    elif not isinstance(value, str):
        value = str(value)
    arr[loc] = value

Type guard

import pandas as pd
def is_assignable_string_scalar(v) -> bool:
    return isinstance(v, str) or pd.isna(v)

Try / catch

try:
    s.iloc[i] = value
except TypeError as e:
    if 'Invalid value' in str(e):
        s.iloc[i] = str(value)
    else:
        raise

Prevention

When it happens

Trigger: Executing `s.iloc[0] = 5` or `arr[0] = 3.14` on a Series/array with dtype 'string[pyarrow]'. The scalar branch at string_arrow.py:333 raises after is_scalar and isna checks pass but isinstance(value, str) fails.

Common situations: Assigning numeric query results into a string column; filling with a sentinel int instead of a string/NA; loops that write heterogeneous values into a typed column.

Related errors


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