keras-team/keras · error · ValueError

A `Concatenate` layer requires inputs with matching shapes e

Error message

A `Concatenate` layer requires inputs with matching shapes except for the concatenation axis. Received: input_shape={input_shape}

What it means

During Concatenate.build, all input shapes must have the same rank (number of dimensions) apart from the concat axis. This specific raise fires when the set of ranks has more than one value, e.g. merging a rank-3 feature map with a rank-2 vector.

Source

Thrown at keras/src/layers/merging/concatenate.py:87

                # but if tensor shapes are not the same when
                # calling, an exception will be raised.
                if axis != concat_axis and axis_value == 1:
                    del reduced_inputs_shapes[i][axis]

            if len(reduced_inputs_shapes[i]) > self.axis:
                del reduced_inputs_shapes[i][self.axis]
            shape_set.add(tuple(reduced_inputs_shapes[i]))

        if len(shape_set) != 1:
            err_msg = (
                "A `Concatenate` layer requires inputs with matching shapes "
                "except for the concatenation axis. "
                f"Received: input_shape={input_shape}"
            )
            # Make sure all the shapes have same ranks.
            ranks = set(len(shape) for shape in shape_set)
            if len(ranks) != 1:
                raise ValueError(err_msg)
            # Get the only rank for the set.
            (rank,) = ranks
            for axis in range(rank):
                # Skip the Nones in the shape since they are dynamic, also the
                # axis for concat has been removed above.
                unique_dims = set(
                    shape[axis]
                    for shape in shape_set
                    if shape[axis] is not None
                )
                if len(unique_dims) > 1:
                    raise ValueError(err_msg)

    def _merge_function(self, inputs):
        return ops.concatenate(inputs, axis=self.axis)

    def compute_output_shape(self, input_shape):
        if (not isinstance(input_shape, (tuple, list))) or (

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Insert Flatten, GlobalAveragePooling2D, or Reshape so all inputs share rank
  2. Expand dims of the lower-rank tensor (e.g. ops.expand_dims(v, 1)) to match
  3. Double-check the axis parameter — it must be valid for the common rank

Example fix

# before
out = layers.Concatenate()([conv_feat, flat_vec])  # rank 4 vs rank 2

# after
conv_feat = layers.GlobalAveragePooling2D()(conv_feat)  # rank 2
out = layers.Concatenate()([conv_feat, flat_vec])
Defensive patterns

Strategy: validation

Validate before calling

ranks = {len(tuple(t.shape)) for t in inputs}
assert len(ranks) == 1, f'rank mismatch before concat: {ranks}'

Type guard

def same_rank(inputs) -> bool:
    shapes = [tuple(t.shape) for t in inputs]
    return len({len(s) for s in shapes}) == 1

Prevention

When it happens

Trigger: Concatenate()([conv_out, dense_out]) where conv_out is (None,8,8,64) and dense_out is (None,128); merging an image tensor with a flat metadata vector.

Common situations: Fusing CNN features with tabular vectors without reshaping; forgetting Flatten/GlobalAveragePooling before concat; mixing sequence and static features.

Related errors


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