Skip to content

Commit e3ed9a2

Browse files
committed
Engine: Ensure node is sealed when process excepts (#6549)
Processes that hit a certain exception were not being sealed. This would cause problems when trying to export them, which only allows sealed nodes. The problem occurs when another exception occurs while handling the original exception. An example is when `Process.update_outputs` would raise a `ValueError` because an unstored node had be attached as an output. Since this method is called in `on_entered`, which is called when the process entered a new state, it would be called again when it entered the excepted state. Since the process was already excepted, the rest of the state changes is cut short by `plumpy`. This would cause the process to never go to the final `TERMINATED` state and so the `on_terminated` method would not be called, which is where the process' node is sealed. The solution is to check the current state in `on_entered` and if it is `EXCEPTED` to simply return and no longer perform any updates on the node. This should prevent any other exceptions from being hit and ensure the process transitions properly to the final terminated state. The only update that is still performed is to update the process state on the process' node, otherwise it would not properly be shown as excepted. Cherry-pick: cbf672f
1 parent 389fc48 commit e3ed9a2

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

src/aiida/engine/processes/process.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,19 @@ def on_create(self) -> None:
414414
@override
415415
def on_entered(self, from_state: Optional[plumpy.process_states.State]) -> None:
416416
"""After entering a new state, save a checkpoint and update the latest process state change timestamp."""
417+
from plumpy import ProcessState
418+
417419
from aiida.engine.utils import set_process_state_change_timestamp
418420

421+
super().on_entered(from_state)
422+
423+
if self._state.LABEL is ProcessState.EXCEPTED:
424+
# The process is already excepted so simply update the process state on the node and let the process
425+
# complete the state transition to the terminal state. If another exception is raised during this exception
426+
# handling, the process transitioning is cut short and never makes it to the terminal state.
427+
self.node.set_process_state(self._state.LABEL)
428+
return
429+
419430
# For reasons unknown, it is important to update the outputs first, before doing anything else, otherwise there
420431
# is the risk that certain outputs do not get attached before the process reaches a terminal state. Nevertheless
421432
# we need to guarantee that the process state gets updated even if the ``update_outputs`` call excepts, for
@@ -431,7 +442,6 @@ def on_entered(self, from_state: Optional[plumpy.process_states.State]) -> None:
431442

432443
self._save_checkpoint()
433444
set_process_state_change_timestamp(self.node)
434-
super().on_entered(from_state)
435445

436446
@override
437447
def on_terminated(self) -> None:

tests/engine/test_work_chain.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ def illegal(self):
422422
orm.QueryBuilder().append(orm.ProcessNode, tag='node').order_by({'node': {'id': 'desc'}}).first(flat=True)
423423
)
424424
assert node.is_excepted
425+
assert node.is_sealed
425426
assert 'ValueError: Workflow<IllegalWorkChain> tried returning an unstored `Data` node.' in node.exception
426427

427428
def test_same_input_node(self):

0 commit comments

Comments
 (0)