keras-team/keras · error · ValueError

ConvNeXt does not support the `channels_first` image data fo

Error message

ConvNeXt does not support the `channels_first` image data format. Switch to `channels_last` by editing your local config file at ~/.keras/keras.json

What it means

Internal guard in _extract_patches_2d: after the public wrapper normalized types, the 2D path requires an int or a length-2 tuple/list. A length-3 tuple reaching here means a 3D size was supplied to the 2D extractor (or extract_patches_2d was called directly), which cannot be interpreted.

Source

Thrown at keras/src/applications/convnext.py:395

                the 4D tensor output of the last convolutional layer.
            - `avg` means that global average pooling will be applied
                to the output of the last convolutional layer,
                and thus the output of the model will be a 2D tensor.
            - `max` means that global max pooling will be applied.
        classes: optional number of classes to classify images into,
            only to be specified if `include_top` is `True`,
            and if no `weights` argument is specified.
        classifier_activation: A `str` or callable.
            The activation function to use
            on the "top" layer. Ignored unless `include_top=True`.
            Set `classifier_activation=None` to return the logits
            of the "top" layer.

    Returns:
        A model instance.
    """
    if backend.image_data_format() == "channels_first":
        raise ValueError(
            "ConvNeXt does not support the `channels_first` image data "
            "format. Switch to `channels_last` by editing your local "
            "config file at ~/.keras/keras.json"
        )
    if not (weights in {"imagenet", None} or file_utils.exists(weights)):
        raise ValueError(
            "The `weights` argument should be either "
            "`None` (random initialization), `imagenet` "
            "(pre-training on ImageNet), "
            "or the path to the weights file to be loaded."
        )

    if weights == "imagenet" and include_top and classes != 1000:
        raise ValueError(
            'If using `weights="imagenet"` with `include_top=True`, '
            "`classes` should be 1000. "
            f"Received classes={classes}"
        )

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Use a 2-element size (or int) for 2D images; reserve length-3 tuples for volumes
  2. Dispatch on image rank: ndim==4 -> size2d, ndim==5 -> size3d, instead of one shared size
  3. Update stale calls to the private _extract_patches_2d that still pass 3D sizes from before a refactor

Example fix

before: extract_patches_2d(imgs, size=(4, 4, 4)) -> TypeError; after: extract_patches_2d(imgs, size=(4, 4))
Defensive patterns

Strategy: validation

Validate before calling

if images.ndim == 4 and not (isinstance(size, int) or len(size) == 2):
    size = size[:2]  # or raise: 2D path needs a 2-element size

Type guard

def is_2d_size(size) -> bool:
    return isinstance(size, int) or (isinstance(size, (tuple, list)) and len(size) == 2)

Prevention

When it happens

Trigger: Calling the private/public 2D extractor with a 3-element size, e.g. extract_patches(images, size=(2, 2, 2)) on 4D images; invoking keras.src.ops.image.extract_patches_2d directly with a 3D patch spec; branching code that reuses one size variable for both 2D and 3D inputs.

Common situations: A pipeline that handles both MRI volumes and 2D slices with a single config-driven size; refactors where extract_patches was split into 2D/3D paths and the dispatch condition on image rank was inverted or removed.

Related errors


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