pandas-dev/pandas · error · TypeError

Invalid value '{value}' for dtype '{self.dtype}'. Value shou

Error message

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

What it means

StringArray._validate_scalar is invoked by NDArrayBackedExtensionIndex.insert (and similar scalar-insertion paths). If the value is not NA-like and not a str instance, it raises TypeError naming the value, the dtype, and the actual type received.

Source

Thrown at pandas/core/arrays/string_.py:755

        else:
            # Validate that we only store NaN or strings.
            if len(self._ndarray) and not lib.is_string_array(
                self._ndarray, skipna=True
            ):
                raise ValueError("StringArray requires a sequence of strings or NaN")
            if self._ndarray.dtype != "object":
                raise ValueError(
                    "StringArray requires a sequence of strings "
                    "or NaN. Got '{self._ndarray.dtype}' dtype instead."
                )
            # TODO validate or force NA/None to NaN

    def _validate_scalar(self, value):
        # used by NDArrayBackedExtensionIndex.insert
        if isna(value):
            return self.dtype.na_value
        elif not isinstance(value, str):
            raise TypeError(
                f"Invalid value '{value}' for dtype '{self.dtype}'. Value should be a "
                f"string or missing value, got '{type(value).__name__}' instead."
            )
        return value

    @classmethod
    def _from_sequence(
        cls, scalars, *, dtype: Dtype | None = None, copy: bool = False
    ) -> Self:
        if dtype and not (isinstance(dtype, str) and dtype == "string"):
            dtype = pandas_dtype(dtype)
            assert isinstance(dtype, StringDtype) and dtype.storage == "python"
        elif using_string_dtype():
            dtype = StringDtype(storage="python", na_value=np.nan)
        else:
            dtype = StringDtype(storage="python")

        from pandas.core.arrays.masked import BaseMaskedArray

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Convert the value to str before inserting: str(value).
  2. Use pd.NA (or np.nan) when you mean 'missing'.
  3. Build the full index from a cleaned list in one step rather than inserting scalars.

Example fix

// before
idx = idx.insert(0, 123)

// after
idx = idx.insert(0, str(123))
Defensive patterns

Strategy: validation

Validate before calling

value = str(value) if not (pd.isna(value) or isinstance(value, str)) else value
idx = idx.insert(0, value)

Type guard

import pandas as pd

def is_string_or_na(v) -> bool:
    return isinstance(v, str) or pd.isna(v)

Prevention

When it happens

Trigger: Calling string_index.insert(0, 123), string_index.append(1.5), or any index operation that funnels a non-string scalar through _validate_scalar on a StringArray-backed index.

Common situations: Appending numeric or mixed-type values to a string-typed Index; building an index incrementally from heterogeneous data.

Related errors


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