Error database

IndexError: Target N is out of bounds (CrossEntropyLoss)

A class label is outside the range your output layer allows — labels must run 0 to C-1. Usually labels start at 1, or the output layer has too few units.

The message you saw
IndexError: Target N is out of bounds (CrossEntropyLoss)

By Updated

The error

Output
IndexError: Target 5 is out of bounds.

On GPU, the identical bug surfaces as the cryptic device-side assert instead — which is why re-running on CPU to get this readable message is a standard debugging move.

What it means

CrossEntropyLoss receives your model's outputs — one score per class — and a target class index per sample. With an output layer of size C, valid targets are 0 through C-1. A target of 5 arrived when the output layer has 5 units (indices 0-4) or fewer. The loss cannot look up a score for a class the model does not produce.

Why it happens

Two mismatches cover nearly every case:

  • Labels start at 1. Datasets labelled 1..N are everywhere. With num_classes=N, label N is out of bounds by one.
  • The output layer is too small. You counted classes wrongly, or a new class appeared in the data after the model was defined.

A third: sentinel values like -1 for "unlabelled" reaching the loss unfiltered. Negative targets raise the same family of errors.

How to fix it

1. Print the actual label range and the output size — the diff is the bug.

python
print(targets.min().item(), targets.max().item())
print(model.fc.out_features)          # or your final layer's name
Output
1 5
5

Labels 1-5 with 5 outputs: off by one.

2. Shift 1-based labels down to 0-based.

python
targets = targets - 1

Do it once, in the Dataset, so every consumer sees consistent labels.

3. Or size the output layer from the data, not from memory.

python
num_classes = int(targets.max().item()) + 1
model.fc = nn.Linear(model.fc.in_features, num_classes)

Counting distinct labels with len(torch.unique(targets)) is a cross-check — if the two numbers differ, some class indices are unused or out of range.

4. Handle sentinel labels explicitly.

python
criterion = nn.CrossEntropyLoss(ignore_index=-1)

Or filter those rows out before the loss.

5. Remember what CrossEntropyLoss wants. Raw logits of shape [N, C], and Long targets of shape [N] holding class indices — not one-hot vectors, and no softmax applied by you.

How to prevent it

Build a single label-mapping step into data loading: map raw labels to 0..C-1, store the mapping, and derive num_classes from it. Assert once per epoch during development: assert targets.max() < C and targets.min() >= 0. Cheap, and it turns a mid-training crash into an immediate clear failure.