keras-team/keras · error · ValueError

`data_format` should be `"channels_last"` (channel after row

Error message

`data_format` should be `"channels_last"` (channel after row and column) or `"channels_first"` (channel before row and column). Received: {data_format}

What it means

ImageDataGenerator accepts data_format of exactly 'channels_last' or 'channels_first'. The value determines which axis is treated as channels in fit()/transforms.

Source

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

        self.zca_whitening = zca_whitening
        self.zca_epsilon = zca_epsilon
        self.rotation_range = rotation_range
        self.width_shift_range = width_shift_range
        self.height_shift_range = height_shift_range
        self.shear_range = shear_range
        self.zoom_range = zoom_range
        self.channel_shift_range = channel_shift_range
        self.fill_mode = fill_mode
        self.cval = cval
        self.horizontal_flip = horizontal_flip
        self.vertical_flip = vertical_flip
        self.rescale = rescale
        self.preprocessing_function = preprocessing_function
        self.dtype = dtype
        self.interpolation_order = interpolation_order

        if data_format not in {"channels_last", "channels_first"}:
            raise ValueError(
                '`data_format` should be `"channels_last"` '
                "(channel after row and column) or "
                '`"channels_first"` (channel before row and column). '
                f"Received: {data_format}"
            )
        self.data_format = data_format
        if data_format == "channels_first":
            self.channel_axis = 1
            self.row_axis = 2
            self.col_axis = 3
        if data_format == "channels_last":
            self.channel_axis = 3
            self.row_axis = 1
            self.col_axis = 2
        if validation_split and not 0 < validation_split < 1:
            raise ValueError(
                "`validation_split` must be strictly between 0 and 1. "
                f" Received: {validation_split}"

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Use 'channels_last' or 'channels_first' literally
  2. Load/verify the value from config: assert data_format in {'channels_last','channels_first'}

Example fix

// before
ImageDataGenerator(data_format='channel_last')
// after
ImageDataGenerator(data_format='channels_last')
Defensive patterns

Strategy: validation

Validate before calling

assert data_format in {'channels_last', 'channels_first'}, data_format

Type guard

def is_data_format(v): return v in {'channels_last', 'channels_first'}

Try / catch

try: ImageDataGenerator(data_format=dfmt)
except ValueError as e: if 'data_format' in str(e): dfmt = 'channels_last'

Prevention

When it happens

Trigger: ImageDataGenerator(data_format='channel_last') (typo), 'NCHW', or a None passed through.

Common situations: Copying config from other frameworks (NCHW/NHWC naming); typo'd key in a YAML config.

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/6d2f46758266cdc5. Report an issue: GitHub.