pandas-dev/pandas · error · ValueError

axis {axis} is out of bounds for array of dimension {first.n

Error message

axis {axis} is out of bounds for array of dimension {first.ndim}

What it means

Raised by Categorical._concat_same_type when axis is greater than or equal to the number of dimensions of the first array (first.ndim). A 1-D categorical only has axis 0, so axis=1 is out of bounds. This mirrors numpy's axis-bounds semantics for the concat path that builds the union of categoricals.

Source

Thrown at pandas/core/arrays/categorical.py:2692

        codes = self.codes.copy()
        mask = self.isna()
        if func == np.minimum.accumulate:
            codes[mask] = np.iinfo(codes.dtype.type).max
        # no need to change codes for maximum because codes[mask] is already -1
        if not skipna:
            mask = np.maximum.accumulate(mask)

        codes = func(codes)
        codes[mask] = -1
        return self._simple_new(codes, dtype=self._dtype)

    @classmethod
    def _concat_same_type(cls, to_concat: Sequence[Self], axis: AxisInt = 0) -> Self:
        from pandas.core.dtypes.concat import union_categoricals

        first = to_concat[0]
        if axis >= first.ndim:
            raise ValueError(
                f"axis {axis} is out of bounds for array of dimension {first.ndim}"
            )

        if axis == 1:
            # Flatten, concatenate then reshape
            if not all(x.ndim == 2 for x in to_concat):
                raise ValueError

            # pass correctly-shaped to union_categoricals
            tc_flat = []
            for obj in to_concat:
                tc_flat.extend([obj[:, i] for i in range(obj.shape[1])])

            res_flat = cls._concat_same_type(tc_flat, axis=0)

            result = res_flat.reshape(len(first), -1, order="F")
            return result

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use axis=0 (the only valid axis for 1-D categoricals) and reshape afterward.
  2. Construct the DataFrame via pd.DataFrame({...}) instead of pd.concat(axis=1) for column-wise assembly of categorical Series.
  3. Verify ndim of inputs and pass an axis strictly less than ndim.

Example fix

// before
pd.concat([pd.Categorical(['a']), pd.Categorical(['b'])], axis=1)  # ValueError

// after
pd.DataFrame({'x': pd.Categorical(['a']), 'y': pd.Categorical(['b'])})
Defensive patterns

Strategy: validation

Validate before calling

def safe_concat(parts, axis):
    first = parts[0]
    if axis >= first.ndim:
        raise ValueError(f'axis {axis} out of bounds for ndim {first.ndim}; use DataFrame ctor')
    return pd.concat(parts, axis=axis)

Type guard

from typing import Any

def axis_in_bounds(obj: Any, axis: int) -> bool:
    return 0 <= axis < getattr(obj, 'ndim', 1)

Try / catch

try:
    pd.concat(parts, axis=axis)
except ValueError as e:
    if 'out of bounds for array of dimension' in str(e):
        result = pd.concat(parts, axis=0)
    else:
        raise

Prevention

When it happens

Trigger: Calling pd.concat([cat1, cat2], axis=1) where the inputs are 1-D Categorical arrays routed through _concat_same_type; or an internal caller passing an axis that exceeds ndim. CategoricalIndex column-wise concat is the typical surface.

Common situations: Building a DataFrame from two Categorical Series with axis=1 (column-wise) where pandas falls into the same-type categorical concat path; or passing user-supplied axis values to groupby/concat internals.

Related errors


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