keras-team/keras · error · ValueError
The `mask` passed to the `TimeDistributed` layer has a shape
Error message
The `mask` passed to the `TimeDistributed` layer has a shape {mask_shape} that is incompatible with the input shape {input_shape}. The first two dimensions of the mask (batch size and timesteps) must match the input's first two dimensions. Expected mask shape prefix: ({input_shape[0]}, {input_shape[1]}). What it means
After confirming the mask is at least 2D, TimeDistributed verifies that the mask's first two dimensions (batch and timesteps) equal the input's first two dimensions whenever both are known. A differently-sized mask would be broadcast against the wrong timesteps and silently zero out valid steps, so the layer raises instead.
Source
Thrown at keras/src/layers/rnn/time_distributed.py:100
"The `mask` passed to the `TimeDistributed` layer must be "
"at least 2D (e.g., `(batch_size, timesteps)`), but it has "
f"{len(mask_shape)} dimension(s) with shape {mask_shape}."
)
# Check batch size and timesteps dimensions match
batch_mismatch = (
input_shape[0] is not None
and mask_shape[0] is not None
and input_shape[0] != mask_shape[0]
)
time_mismatch = (
input_shape[1] is not None
and mask_shape[1] is not None
and input_shape[1] != mask_shape[1]
)
if batch_mismatch or time_mismatch:
raise ValueError(
"The `mask` passed to the `TimeDistributed` layer has a "
f"shape {mask_shape} that is incompatible with the input "
f"shape {input_shape}. The first two dimensions of the "
"mask (batch size and timesteps) must match the input's "
"first two dimensions. Expected mask shape prefix: "
f"({input_shape[0]}, {input_shape[1]})."
)
input_shape = ops.shape(inputs)
def time_distributed_transpose(data):
"""Swaps the timestep and batch dimensions of a tensor."""
axes = [1, 0, *range(2, len(data.shape))]
return ops.transpose(data, axes=axes)
inputs = time_distributed_transpose(inputs)
if mask is not None:
mask = time_distributed_transpose(mask)View on GitHub (pinned to 7a34a03db6)
Solutions
- Regenerate the mask from the same input (e.g. keep Embedding(mask_zero=True) immediately upstream so Keras propagates the correct mask)
- Make sure sequence padding maxlen matches the mask's timestep dimension
- Compare input.shape[:2] vs mask.shape[:2] before calling and reshape or recompute if unequal
Example fix
# before mask = old_mask # shape (32, 50) out = td_layer(x, mask=mask) # x shape (32, 100) # after # let Keras propagate the mask automatically model = keras.Sequential([keras.layers.Embedding(vocab, dim, mask_zero=True), td_layer]) out = model(x)
Defensive patterns
Strategy: validation
Validate before calling
if mask is not None:
ins, msk = tuple(inputs.shape[:2]), tuple(mask.shape[:2])
assert ins == msk or None in ins + msk, f'mask {msk} != input {ins}'
out = td_layer(inputs, mask=mask) Type guard
def mask_matches_input(mask, x) -> bool:
return tuple(mask.shape[:2]) == tuple(x.shape[:2]) Prevention
- Use the same padding maxlen for inputs and masks
- Never reuse masks across differently sized batches
When it happens
Trigger: Passing a mask of shape (batch, other_timesteps) or (other_batch, timesteps) to TimeDistributed; reusing a cached mask from a differently-batched input; a custom compute_mask that hardcodes or slices timesteps incorrectly.
Common situations: Padding/truncating sequences to a different maxlen than the mask was built with; splitting batches but reusing the old mask; pipelines that cache masks; stateful RNN reuse across sequences of different lengths.
Related errors
- The `mask` passed to the `TimeDistributed` layer must be at
- `mask` should be a list. Received: mask={mask}
- `inputs` should be a list. Received: inputs={inputs}
- The lists `inputs` and `mask` should have the same length. R
- `mask` should be a list. Received mask={mask}
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/a6a75afef3c7c341.
Report an issue: GitHub.