# 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.