pandas-dev/pandas · error · ValueError

Value must be one of python|pyarrow

Error message

Value must be one of python|pyarrow

What it means

ValueError raised by is_valid_string_storage() in pandas/core/config_init.py:500, the validator for the 'mode.string_storage' option which selects the default backing dtype for StringDtype. The function's legal_values list actually permits ['auto','python','pyarrow'], but the error message only mentions 'python|pyarrow' (a known message/behavior mismatch worth noting). Any other value raises at set-option time.

Source

Thrown at pandas/core/config_init.py:500

    cf.register_option(
        "max_threads",
        None,
        max_threads_doc,
        validator=_is_positive_int_or_none,
    )


string_storage_doc = """
: string
    The default storage for StringDtype.
"""


def is_valid_string_storage(value: Any) -> None:
    legal_values = ["auto", "python", "pyarrow"]
    if value not in legal_values:
        msg = "Value must be one of python|pyarrow"
        raise ValueError(msg)


with cf.config_prefix("mode"):
    cf.register_option(
        "string_storage",
        "auto",
        string_storage_doc,
        # validator=is_one_of_factory(["python", "pyarrow"]),
        validator=is_valid_string_storage,
    )


# Set up the io.excel specific reader configuration.
reader_engine_doc = """
: string
    The default Excel reader engine for '{ext}' files. Available options:
    auto, {others}.
"""

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use one of the exact lowercase tokens: 'auto', 'python', or 'pyarrow'.
  2. Install pyarrow before selecting 'pyarrow' (it raises a separate ImportError otherwise).
  3. Normalize config input: value = str(value).strip().lower(); if value not in {'auto','python','pyarrow'}: keep default rather than calling set_option.
  4. Note the message says 'python|pyarrow' but 'auto' is also accepted in recent versions; prefer 'auto' to defer the choice based on pyarrow availability.

Example fix

// before
pd.set_option('mode.string_storage', 'PyArrow')  # ValueError

// after
pd.set_option('mode.string_storage', 'pyarrow')
# or, to defer to availability:
pd.set_option('mode.string_storage', 'auto')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

_VALID_STRING_STORAGE = {'auto', 'python', 'pyarrow'}

def set_string_storage(value: str) -> None:
    v = str(value).strip().lower()
    if v not in _VALID_STRING_STORAGE:
        raise ValueError(f'string_storage must be one of {sorted(_VALID_STRING_STORAGE)}, got {value!r}')
    if v == 'pyarrow':
        try:
            import pyarrow  # noqa: F401
        except ImportError as e:
            raise ImportError('mode.string_storage=pyarrow requires pyarrow installed') from e
    pd.set_option('mode.string_storage', v)

Type guard

def is_valid_string_storage(value) -> bool:
    return isinstance(value, str) and value.strip().lower() in {'auto', 'python', 'pyarrow'}

Try / catch

import pandas as pd

try:
    pd.set_option('mode.string_storage', value)
except ValueError as e:
    if 'python|pyarrow' in str(e) or 'string_storage' in str(e):
        # keep current default; do not crash the app over a config typo
        pd.set_option('mode.string_storage', 'auto')
    else:
        raise

Prevention

When it happens

Trigger: pd.set_option('mode.string_storage', 'Arrow'); pd.set_option('mode.string_storage', 'str'); pd.set_option('mode.string_storage', 'numpy'); misspelled 'pyarow'; passing a non-string value such as None, True, or an int; reading the value from config and passing it unvalidated.

Common situations: Confusing the option value with the dtype name (e.g. 'StringDtype', 'ArrowDtype'); using a casing the validator does not normalize ('Python', 'PyArrow'); older pandas versions that only accepted 'python'/'pyarrow' before 'auto' was added; env/config-driven setups that pass through arbitrary strings; users assuming 'numpy' object storage is selectable here (it is not).

Related errors


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