keras-team/keras · error · ValueError

'row_axis', 'col_axis', and 'channel_axis' must be distinct

Error message

'row_axis', 'col_axis', and 'channel_axis' must be distinct

What it means

apply_affine_transform requires three distinct axis arguments (row_axis, col_axis, channel_axis) that together describe which dimensions of a 3D image tensor are rows, columns, and channels. If any two are equal the mapping is ambiguous, so Keras raises this ValueError before doing any work. It lives in the legacy keras.preprocessing.image module.

Source

Thrown at keras/src/legacy/preprocessing/image.py:1795

    shear=0,
    zx=1,
    zy=1,
    row_axis=1,
    col_axis=2,
    channel_axis=0,
    fill_mode="nearest",
    cval=0.0,
    order=1,
):
    """Applies an affine transformation specified by the parameters given.

    DEPRECATED.
    """
    # Input sanity checks:
    # 1. x must 2D image with one or more channels (i.e., a 3D tensor)
    # 2. channels must be either first or last dimension
    if np.unique([row_axis, col_axis, channel_axis]).size != 3:
        raise ValueError(
            "'row_axis', 'col_axis', and 'channel_axis' must be distinct"
        )

    # shall we support negative indices?
    valid_indices = set([0, 1, 2])
    actual_indices = set([row_axis, col_axis, channel_axis])
    if actual_indices != valid_indices:
        raise ValueError(
            f"Invalid axis' indices: {actual_indices - valid_indices}"
        )

    if x.ndim != 3:
        raise ValueError("Input arrays must be multi-channel 2D images.")
    if channel_axis not in [0, 2]:
        raise ValueError(
            "Channels are allowed and the first and last dimensions."
        )

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Set the three axes to a permutation of 0, 1, 2, e.g. row_axis=0, col_axis=1, channel_axis=2 (channels-last) or row_axis=2, col_axis=0, channel_axis=1 (channels-first)
  2. Check computed/looped axis assignments for duplicates before calling
  3. For the random_* wrappers, prefer their channel_axis argument instead of manual axis triples

Example fix

# before
apply_affine_transform(img, theta=15, row_axis=0, col_axis=0, channel_axis=2)
# after
apply_affine_transform(img, theta=15, row_axis=0, col_axis=1, channel_axis=2)
Defensive patterns

Strategy: validation

Validate before calling

axes = {row_axis, col_axis, channel_axis}
if len(axes) != 3:
    raise ValueError('axis arguments must be distinct')

Type guard

def valid_axes(r, c, ch):
    return len({r, c, ch}) == 3

Prevention

When it happens

Trigger: Calling apply_affine_transform (directly or via random_rotation, random_shift, random_shear, random_zoom, apply_transform) with two equal axis values, e.g. row_axis=1, col_axis=1, channel_axis=2, or a copy-paste error repeating the same default twice.

Common situations: Hand-writing axis permutations for channels-first vs channels-last images when porting old scipy.ndimage-style augmentation code, or loops that assign axis indices programmatically and accidentally alias two of them.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/f10f911e497a60af. Report an issue: GitHub.