pandas-dev/pandas · error · ValueError

Storage must be 'python' or 'pyarrow'. Got {storage} instead

Error message

Storage must be 'python' or 'pyarrow'. Got {storage} instead.

What it means

StringDtype.__init__ validates that the storage argument is exactly one of 'python' or 'pyarrow'. Any other value (including None after config resolution, or typos) raises ValueError. When storage is None it is first resolved from pd.options.mode.string_storage, so a misconfigured global option can also surface here.

Source

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

    _metadata = ("storage", "_na_value")  # type: ignore[assignment]

    def __init__(
        self,
        storage: str | None = None,
        na_value: libmissing.NAType | float = libmissing.NA,
    ) -> None:
        # infer defaults
        if storage is None:
            storage = config["mode"]["string_storage"]
            if storage == "auto":
                if HAS_PYARROW:
                    storage = "pyarrow"
                else:
                    storage = "python"

        # validate options
        if storage not in {"python", "pyarrow"}:
            raise ValueError(
                f"Storage must be 'python' or 'pyarrow'. Got {storage} instead."
            )
        if storage == "pyarrow" and not HAS_PYARROW:
            raise ImportError(
                f"pyarrow>={PYARROW_MIN_VERSION} is required for PyArrow "
                "backed StringArray."
            )

        if isinstance(na_value, float) and np.isnan(na_value):
            # when passed a NaN value, always set to np.nan to ensure we use
            # a consistent NaN value (and we can use `dtype.na_value is np.nan`)
            na_value = np.nan
        elif na_value is not libmissing.NA:
            raise ValueError(f"'na_value' must be np.nan or pd.NA, got {na_value}")

        self._storage = cast("str", storage)
        self._na_value = na_value

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use exactly 'python' or 'pyarrow' as the storage value.
  2. If using config, verify pd.options.mode.string_storage is 'python' or 'pyarrow' before relying on storage=None.
  3. Validate dynamic storage strings against {'python','pyarrow'} before passing to StringDtype.

Example fix

// before
dtype = pd.StringDtype(storage='numpy')

// after
dtype = pd.StringDtype(storage='python')
Defensive patterns

Strategy: validation

Validate before calling

VALID_STORAGES = {'python', 'pyarrow'}
storage = 'python' if storage not in VALID_STORAGES else storage
dtype = pd.StringDtype(storage=storage)

Prevention

When it happens

Trigger: Calling StringDtype(storage='numpy'), StringDtype(storage='foo'), pd.array(data, dtype='string[foo]'), or setting pd.options.mode.string_storage to an invalid value and then constructing a StringDtype with storage=None.

Common situations: Typos in dtype strings like 'string[numpy]' or 'string[arrow]'; programmatically building storage names; a stale or wrong value in mode.string_storage config.

Related errors


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