diff --git a/docs/source/howto/query.rst b/docs/source/howto/query.rst
index 711067ce2a..4916cb508e 100644
--- a/docs/source/howto/query.rst
+++ b/docs/source/howto/query.rst
@@ -97,6 +97,7 @@ For example, you can iterate over the results of your query in a for loop:
When looping over the result of a query, use the ``iterall`` (or ``iterdict``) generator instead of ``all`` (or ``dict``).
This avoids loading the entire query result into memory, and it also delays committing changes made to AiiDA objects inside the loop until the end of the loop is reached.
+ If an exception is raised before the loop ends, all changes are reverted.
.. _how-to:query:filters:
diff --git a/tests/orm/test_querybuilder.py b/tests/orm/test_querybuilder.py
index d532fd99c1..341e08836c 100644
--- a/tests/orm/test_querybuilder.py
+++ b/tests/orm/test_querybuilder.py
@@ -1475,6 +1475,31 @@ def test_len_results(self):
qb.append(orm.Data, with_incoming='parent')
assert len(qb.all()) == qb.count()
+ @pytest.mark.usefixtures('aiida_profile_clean')
+ def test_iterall_except(self):
+ """Test ``QueryBuilder.iterall`` uses a transaction and if interrupted, changes are reverted.
+
+ In this test, 10 nodes are created which are then looped over and for each one, another node is stored, but
+ before the loop can finish, an exception is raised. At then, the number of nodes should still be ten as the new
+ ones that were being created in the transaction should have been reverted.
+ """
+ assert orm.QueryBuilder().append(orm.Data).count() == 0
+
+ count = 10
+
+ for _ in range(count):
+ orm.Data().store()
+
+ try:
+ for index, _ in enumerate(orm.QueryBuilder().append(orm.Data).iterall()):
+ orm.Data().store()
+ if index >= count - 2:
+ raise RuntimeError('some error')
+ except RuntimeError:
+ pass
+
+ assert orm.QueryBuilder().append(orm.Data).count() == count
+
def test_iterall_with_mutation(self):
"""Test that nodes can be mutated while being iterated using ``QueryBuilder.iterall``.