PyTorch
tensor
backward error
grad_fn
CopySlices

An error when calling tensor.backward in pytorch may caused by grad_fnCopySlices

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

If you see grad_fn=<CopySlices> near a PyTorch backward() failure, that name is usually a clue rather than the root cause. In practice, the real problem is often an in-place slice assignment or a tensor mutation that changed a value Autograd still needed for gradient computation.

What CopySlices Usually Means

PyTorch builds a dynamic computation graph as tensor operations run. When you assign into part of a tensor, PyTorch may create a graph node related to copying into slices. That is where CopySlices comes from.

A simplified example:

python
1import torch
2
3x = torch.randn(4, requires_grad=True)
4y = x * 2
5z = y.clone()
6z[:2] = 0
7loss = z.sum()
8loss.backward()

This code may work or fail depending on the exact sequence of operations, but it shows the pattern: slice assignment becomes part of the graph. The presence of CopySlices is not automatically wrong. The error usually appears when that mutation conflicts with what Autograd expects to read during backpropagation.

In-Place Operations Are the Common Trigger

The most frequent failure mode is an in-place modification on a tensor that still participates in gradient computation.

python
1import torch
2
3x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
4y = x * x
5y[0] = 0.0
6loss = y.sum()
7loss.backward()

This kind of pattern can produce errors like:

  • one of the variables needed for gradient computation has been modified by an inplace operation
  • leaf variable was used in an in-place operation

The exact message varies, but the fix is similar: avoid mutating tensors that Autograd still needs.

Prefer Out-of-Place Transformations

Instead of assigning into slices, create a new tensor with a differentiable expression.

python
1import torch
2
3x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
4y = x * x
5mask = torch.tensor([0.0, 1.0, 1.0])
6z = y * mask
7loss = z.sum()
8loss.backward()
9print(x.grad)

This is often better because it expresses the same idea without mutating an intermediate tensor in place.

Other good replacements include:

  • 'torch.where'
  • 'torch.cat'
  • 'torch.stack'
  • arithmetic masking

These patterns make the gradient path more predictable than slice mutation.

Clone Carefully When You Need a Writable Copy

If you truly need to edit a tensor, work on a cloned tensor and understand what should remain connected to the graph.

python
1import torch
2
3x = torch.randn(5, requires_grad=True)
4y = x * 3
5z = y.clone()
6z = z.index_fill(0, torch.tensor([0, 1]), 0.0)
7loss = z.sum()
8loss.backward()

Cloning can help, but it is not magic. If you mutate a clone in a way that still breaks the expected graph semantics, the error can remain. The goal is not "add clone() everywhere." The goal is "stop modifying tensors in place when a functional alternative exists."

Debug with Anomaly Detection

When the graph is complex, enable anomaly detection to pinpoint the operation that broke gradient computation.

python
import torch

torch.autograd.set_detect_anomaly(True)

This slows execution, so it is mainly for debugging. Still, it is one of the fastest ways to move from a vague backward() failure to the exact operation that introduced the bad mutation.

Also inspect:

  • whether the tensor is a leaf
  • whether requires_grad=True
  • whether you are using methods ending in _, which are usually in-place

Examples include add_, copy_, zero_, and slice assignment.

Common Pitfalls

  • Treating grad_fn=<CopySlices> as the real bug instead of the symptom of an unsafe mutation.
  • Modifying tensors in place after they have already been used to build later graph nodes.
  • Applying slice assignment where a functional operation such as torch.where would be clearer.
  • Adding clone() blindly without understanding which tensor should remain part of the graph.
  • Debugging backward() failures without enabling anomaly detection on complex graphs.

Summary

  • 'CopySlices usually points to slice assignment inside the Autograd graph.'
  • The real problem is often an in-place modification that invalidates gradient computation.
  • Prefer out-of-place tensor operations over manual slice mutation.
  • Use clone() only when you understand the graph implications.
  • Turn on anomaly detection to locate the exact operation that broke backward().

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design