## TL;DR

For "QuantumFunctionError: Backpropagation is only supported when shots=None.": use "adjoint" when the parameter count is large (much lower memory, similar runtime). Apply the method from step 2's matrix, not the one that worked in a tutorial with a different configuration.

```text
QuantumFunctionError: Backpropagation is only supported when shots=None.
```

## When to use

You are seeing this: The error message names the illegal combination directly, match it before changing anything. Use this skill when you run into "Choose the right PennyLane diff_method and fix gradient configuration errors".

## When not to use

If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.

## Versions

No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.

## Choose the right diff_method and fix gradient configuration errors in PennyLane

Use this when a PennyLane gradient call raises `QuantumFunctionError`,
`ValueError`, or `NotImplementedError` naming the differentiation method, or when
you are choosing `diff_method` for a new QNode. The error message names the
illegal combination directly, match it before changing anything.

## 1. Read the exact error, it names the illegal combination

| Error text | Meaning | Fix |
|---|---|---|
| `Computing the gradient of circuits that return the state with the parameter-shift rule gradient transform is not supported, as it is a hardware-compatible method.` | `diff_method="parameter-shift"` on a circuit returning `qml.state()` (or `qml.density_matrix`) | On a simulator with `shots=None`, switch to `diff_method="backprop"`; or return `qml.expval` instead of the state |
| `QuantumFunctionError: Backpropagation is only supported when shots=None.` | `diff_method="backprop"` with finite shots | Set `shots=None` on the device, or switch to `diff_method="parameter-shift"` |
| `QuantumFunctionError: Adjoint differentiation method does not support measurement state` | `diff_method="adjoint"` on a circuit returning `qml.state()` | Adjoint only supports expectation values of observables; use `"backprop"` or change the measurement |
| `NotImplementedError: Computing the gradient of broadcasted tapes with respect to the broadcasted parameters using the parameter-shift rule gradient transform is currently not supported.` | A trainable parameter is broadcast (e.g. one RX over a batch of angles) under parameter-shift | Do not make the broadcast axis trainable: loop over the batch in Python, or use `"backprop"` on a simulator |
| `QuantumFunctionError: Device [...] does not support device with requested circuit.` | `diff_method="device"` on a device with no native jacobian (e.g. `default.qubit`) | Use `"best"`, `"backprop"`, `"adjoint"`, or `"parameter-shift"` instead, `"device"` needs a device that provides its own jacobian |

## 2. Pick diff_method from device x shots x measurement

Classify your configuration first; the matrix below gives the method:

- **Simulator** (`default.qubit`, `lightning.qubit`) + `shots=None` + `qml.expval`/`qml.var`/`qml.probs`: `diff_method="best"` (the default) resolves to backprop on `default.qubit`, exact and usually cheapest. Use `"adjoint"` when the parameter count is large (much lower memory, similar runtime). Both are simulator-only.
- **Simulator + finite shots** (`shots=1000`, etc.): only hardware-compatible methods work, `"parameter-shift"`, `"finite-diff"`, `"hadamard"`. Backprop raises the `shots=None` error; adjoint warns and computes the gradient analytically anyway, so the gradient no longer matches the noisy forward pass.
- **Hardware device**: only `"parameter-shift"`, `"finite-diff"`, or `"hadamard"`. Backprop and adjoint are never available, this is documented, not a bug.
- **Circuit returns `qml.state()`**: only `"backprop"` on a simulator with `shots=None`. Parameter-shift and adjoint both refuse (see the error table). Never on hardware.
- **Circuit returns `qml.sample` or `qml.counts`**: no gradient under any method or device. The QNode must return `qml.expval` (or `qml.probs`) to train.

## 3. Know the cost before you pick

Parameter-shift needs 2 circuit evaluations per trainable parameter per gradient
step, so gradient cost scales linearly with parameter count. On simulators,
backprop and adjoint are usually cheaper and exact, prefer them whenever the
configuration in step 2 allows. Finite shots make parameter-shift gradients
noisy estimators; that is expected, not a bug.

## 4. Checklist for the failing gradient call

1. Copy the full error text; match it to the table in step 1.
2. Confirm the three facts: device class (simulator vs hardware), `shots`
 setting (`None` vs finite), and the returned measurement type.
3. Apply the method from step 2's matrix, not the one that worked in a
 tutorial with a different configuration.
4. Re-run the gradient call (`qml.grad(circuit)(params)` or the interface's
 backward pass) and confirm the error is gone before tuning anything else.
