Repository: PennyLaneAI/pennylane

Issue:
[BUG] Inline transforms vs. Decorator transforms
### Expected behavior

This  script:

```
def circuit(circuit_param):
    qml.RY(circuit_param, wires=0)
    qml.Hadamard(wires=0)
    qml.T(wires=0)

def noise(noise_param, wires):
    qml.CRX(noise_param, wires=[0,1])
    qml.CNOT(wires=[1,0])
    
dev = qml.device("default.mixed", wires=2)

noise_param = 0.3
    
@qml.qnode(dev)
@qml.transforms.insert(noise, noise_param, position="all")
def noisy_circuit(circuit_param):
        
    circuit(circuit_param)
    
    return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliY(0)), qml.expval(qml.PauliZ(0))

noisy_circuit(0.4)
```
And this one
```
def circuit(circuit_param):
    qml.RY(circuit_param, wires=0)
    qml.Hadamard(wires=0)
    qml.T(wires=0)

def noise(noise_param, wires):
    qml.CRX(noise_param, wires=[0,1])
    qml.CNOT(wires=[1,0])
    
dev = qml.device("default.mixed", wires=2)

noise_param = 0.3
    
@qml.qnode(dev)
def noisy_circuit(circuit_param):
        
    qml.transforms.insert(noise, noise_param, position="all")(circuit)(circuit_param)
    
    return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliY(0)), qml.expval(qml.PauliZ(0))

noisy_circuit(0.4)
```
should both return `array([0.64497588, 0.61505021, 0.40503904])`

### Actual behavior

The second script works, but the first one returns errors.

### Additional information

I know this is an issue with how tapes are handled in either case. Please reconsider how this interacts with users.

### Source code

```shell
def circuit(circuit_param):
    qml.RY(circuit_param, wires=0)
    qml.Hadamard(wires=0)
    qml.T(wires=0)

def noise(noise_param, wires):
    qml.CRX(noise_param, wires=[0,1])
    qml.CNOT(wires=[1,0])
    
dev = qml.device("default.mixed", wires=2)

noise_param = 0.3
    
@qml.qnode(dev)
@qml.transforms.insert(noise, noise_param, position="all")
def noisy_circuit(circuit_param):
        
    circuit(circuit_param)
    
    return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliY(0)), qml.expval(qml.PauliZ(0))

noisy_circuit(0.4)
```


### Tracebacks

```shell
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\anaconda3\lib\site-packages\pennylane\tape\tape.py in expand_tape(tape, depth, stop_at, expand_measurements)
    156             try:
--> 157                 rotations, diag_obs = qml.grouping.diagonalize_qwc_pauli_words(
    158                     tape._obs_sharing_wires

~\anaconda3\lib\site-packages\pennylane\grouping\transformations.py in diagonalize_qwc_pauli_words(qwc_grouping)
    139     if not are_pauli_words_qwc(qwc_grouping):
--> 140         raise ValueError("The list of Pauli words are not qubit-wise commuting.")
    141 

ValueError: The list of Pauli words are not qubit-wise commuting.

The above exception was the direct cause of the following exception:

QuantumFunctionError                      Traceback (most recent call last)
~\anaconda3\lib\site-packages\pennylane\transforms\qfunc_transforms.py in __call__(self, tape, *args, **kwargs)
    169         with tape_class() as new_tape:
--> 170             self.transform_fn(tape, *args, **kwargs)
    171 

~\anaconda3\lib\site-packages\pennylane\transforms\insert_ops.py in insert(circuit, op, op_args, position, before)
    212     # TODO: change this to be cleaner and more robust
--> 213     circuit = circuit.expand(
    214         stop_at=lambda op: not hasattr(qml.templates, op.name) and not isinstance(op, Adjoint)

~\anaconda3\lib\site-packages\pennylane\tape\tape.py in expand(self, depth, stop_at, expand_measurements)
    686         """
--> 687         new_tape = expand_tape(
    688             self, depth=depth, stop_at=stop_at, expand_measurements=expand_measurements

~\anaconda3\lib\site-packages\pennylane\tape\tape.py in expand_tape(tape, depth, stop_at, expand_measurements)
    172 
--> 173                 raise qml.QuantumFunctionError(
    174                     "Only observables that are qubit-wise commuting "

QuantumFunctionError: Only observables that are qubit-wise commuting Pauli words can be returned on the same wire, some of the following measurements do not commute:
[expval(PauliX(wires=[0])), expval(PauliY(wires=[0])), expval(PauliZ(wires=[0]))]

During handling of the above exception, another exception occurred:

IndexError                                Traceback (most recent call last)
~\anaconda3\lib\site-packages\pennylane\qnode.py in construct(self, args, kwargs)
    525         with self.tape:
--> 526             self._qfunc_output = self.func(*args, **kwargs)
    527         self._tape._qfunc_output = self._qfunc_output

~\anaconda3\lib\site-packages\pennylane\transforms\qfunc_transforms.py in internal_wrapper(*args, **kwargs)
    201         tape = make_tape(fn)(*args, **kwargs)
--> 202         tape = tape_transform(tape, *transform_args, **transform_kwargs)
    203 

~\anaconda3\lib\site-packages\pennylane\transforms\qfunc_transforms.py in __call__(self, tape, *args, **kwargs)
    169         with tape_class() as new_tape:
--> 170             self.transform_fn(tape, *args, **kwargs)
    171 

~\anaconda3\lib\site-packages\pennylane\tape\tape.py in __exit__(self, exception_type, exception_value, traceback)
    389         try:
--> 390             super().__exit__(exception_type, exception_value, traceback)
    391             # After other optimizations in #2963, #2986 and follow-up work, we should check whether

~\anaconda3\lib\site-packages\pennylane\queuing.py in __exit__(self, exception_type, exception_value, traceback)
    127         """Remove this instance from the global list of active contexts."""
--> 128         QueuingContext._active_contexts.pop()
    129 

IndexError: pop from an empty deque

During handling of the above exception, another exception occurred:

IndexError                                Traceback (most recent call last)
<ipython-input-33-37d3113aba14> in <module>
     20     return qml.expval(qml.PauliX(0)), qml.expval(qml.PauliY(0)), qml.expval(qml.PauliZ(0))
     21 
---> 22 noisy_circuit(0.4)

~\anaconda3\lib\site-packages\pennylane\qnode.py in __call__(self, *args, **kwargs)
    609 
    610         # construct the tape
--> 611         self.construct(args, kwargs)
    612 
    613         cache = self.execute_kwargs.get("cache", False)

~\anaconda3\lib\site-packages\pennylane\qnode.py in construct(self, args, kwargs)
    524 
    525         with self.tape:
--> 526             self._qfunc_output = self.func(*args, **kwargs)
    527         self._tape._qfunc_output = self._qfunc_output
    528 

~\anaconda3\lib\site-packages\pennylane\tape\tape.py in __exit__(self, exception_type, exception_value, traceback)
    388     def __exit__(self, exception_type, exception_value, traceback):
    389         try:
--> 390             super().__exit__(exception_type, exception_value, traceback)
    391             # After other optimizations in #2963, #2986 and follow-up work, we should check whether
    392             # calling `_process_queue` only if there is no `exception_type` saves time. This would

~\anaconda3\lib\site-packages\pennylane\queuing.py in __exit__(self, exception_type, exception_value, traceback)
    126     def __exit__(self, exception_type, exception_value, traceback):
    127         """Remove this instance from the global list of active contexts."""
--> 128         QueuingContext._active_contexts.pop()
    129 
    130     @abc.abstractmethod

IndexError: pop from an empty deque
```


### System information

```shell
Name: PennyLane
Version: 0.26.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: None
Author-email: None
License: Apache License 2.0
Location: c:\users\alvaro\anaconda3\lib\site-packages
Requires: numpy, appdirs, cachetools, retworkx, toml, autograd, semantic-version, pennylane-lightning, autoray, scipy, networkx
Required-by: PennyLane-SF, pennylane-qulacs, PennyLane-Qchem, PennyLane-Lightning

Platform info:           Windows-10-10.0.19041-SP0
Python version:          3.8.8
Numpy version:           1.22.1
Scipy version:           1.6.2
Installed devices:
- default.gaussian (PennyLane-0.26.0)
- default.mixed (PennyLane-0.26.0)
- default.qubit (PennyLane-0.26.0)
- default.qubit.autograd (PennyLane-0.26.0)
- default.qubit.jax (PennyLane-0.26.0)
- default.qubit.tf (PennyLane-0.26.0)
- default.qubit.torch (PennyLane-0.26.0)
- default.qutrit (PennyLane-0.26.0)
- strawberryfields.fock (PennyLane-SF-0.19.0)
- strawberryfields.gaussian (PennyLane-SF-0.19.0)
- strawberryfields.gbs (PennyLane-SF-0.19.0)
- strawberryfields.remote (PennyLane-SF-0.19.0)
- strawberryfields.tf (PennyLane-SF-0.19.0)
- qulacs.simulator (pennylane-qulacs-0.16.0)
- lightning.qubit (PennyLane-Lightning-0.26.0)
```


### Existing GitHub issues

- [X] I have searched existing GitHub issues to make sure the issue does not already exist.

Discussion:
github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#3182](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (d3e0465) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/315ff3e0ab14a35feeef6d73c26590438bf6b692?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (315ff3e) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##           master    #3182   +/-   ##
=======================================
  Coverage   99.69%   99.69%           
=======================================
  Files         274      274           
  Lines       23885    23922   +37     
=======================================
+ Hits        23811    23848   +37     
  Misses         74       74           
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/operation.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wZXJhdGlvbi5weQ==) | `97.04% <100.00%> (+0.04%)` | :arrow_up: |
| [pennylane/ops/op\_math/composite.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9vcF9tYXRoL2NvbXBvc2l0ZS5weQ==) | `100.00% <100.00%> (ø)` | |
| [pennylane/ops/qubit/hamiltonian.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9oYW1pbHRvbmlhbi5weQ==) | `100.00% <100.00%> (ø)` | |
| [pennylane/queuing.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3182/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3F1ZXVpbmcucHk=) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index e2beb942c..fcc47fcc3 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -206,6 +206,9 @@ keyword argument when using `GellMann`, which determines which of the 8 Gell-Man
 * Fixed a bug where `qml.math.fidelity(non_trainable_state, trainable_state)` failed unexpectedly.
   [(#3160)](https://github.com/PennyLaneAI/pennylane/pull/3160)
 
+* Fixed a bug where `qml.QueuingManager.stop_recording` did not clean up if yielded code raises an exception.
+  [(#3182)](https://github.com/PennyLaneAI/pennylane/pull/3182)
+
 <h3>Contributors</h3>
 
 This release contains contributions from (in alphabetical order):
diff --git a/pennylane/queuing.py b/pennylane/queuing.py
index f044d34f8..c6d480c51 100644
--- a/pennylane/queuing.py
+++ b/pennylane/queuing.py
@@ -145,7 +145,11 @@ class QueuingManager:
         """
         previously_active_contexts = cls._active_contexts
         cls._active_contexts = []
-        yield
+        try:
+            yield
+        except Exception as e:
+            cls._active_contexts = previously_active_contexts
+            raise e
         cls._active_contexts = previously_active_contexts
 
     @classmethod


Test patch:
diff --git a/tests/tape/test_tape.py b/tests/tape/test_tape.py
index 7fa109c4d..1ba8d1fce 100644
--- a/tests/tape/test_tape.py
+++ b/tests/tape/test_tape.py
@@ -1658,6 +1658,15 @@ class TestStopRecording:
         assert len(temp_tape.operations) == 1
         assert temp_tape.operations[0] == op1
 
+    def test_stop_recording_within_tape_cleans_up(self):
+        """Test if some error is raised within a stop_recording context, the previously
+        active contexts are still returned to avoid popping from an empty deque"""
+
+        with pytest.raises(ValueError):
+            with qml.queuing.AnnotatedQueue() as q:
+                with qml.QueuingManager.stop_recording():
+                    raise ValueError
+
 
 def test_get_active_tape():
     """Test that the get_active_tape() function returns the currently