Engineering change order workflow deadlocks when parallel approvals reject simultaneously

Our ECO workflow in Aras 14.0 is experiencing deadlock situations when we have parallel approval paths and both approvers reject at roughly the same time. The workflow gets stuck and can’t proceed forward or backward.

We have a parallel gateway where both design engineering and manufacturing need to approve changes. When both reject simultaneously (within seconds of each other), the workflow hangs. Looking at the workflow map, I can see both rejection paths trying to converge but the join condition doesn’t seem to handle the dual rejection scenario properly.


<parallel_gateway id="DUAL_APPROVAL">
  <path id="design" join_condition="approved"/>
  <path id="mfg" join_condition="approved"/>
</parallel_gateway>

The rejection propagation logic seems flawed - it doesn’t know which rejection path to follow when both fire at once. The workflow just stops and we have to manually abort and restart the ECO. Has anyone dealt with parallel gateway join conditions that handle multiple simultaneous rejections?

This is a classic parallel gateway design issue that requires comprehensive fixes across multiple areas. Let me break down the solution:

Parallel Gateway Configuration: Your current gateway configuration is incomplete because it only defines success conditions. You need to explicitly handle both success and failure scenarios. Modify your parallel gateway to include rejection handling:

The gateway needs three distinct condition checks:

  1. Success: ALL paths approved → proceed to next activity
  2. Partial rejection: ANY path rejected → immediate termination and route to rejection handler
  3. Timeout: ANY path exceeds deadline → escalation

Your current XML only covers scenario 1. Add explicit rejection conditions:


<parallel_gateway id="DUAL_APPROVAL">
  <success_condition>design.approved AND mfg.approved</success_condition>
  <failure_condition>design.rejected OR mfg.rejected</failure_condition>
  <failure_action>terminate_all_paths</failure_action>
</parallel_gateway>

The key is the failure_action directive that tells the workflow engine to immediately terminate all active parallel paths when the failure condition is met.

Join Condition Logic: The join condition needs to be evaluated continuously, not just when paths complete. Implement a state-checking mechanism that monitors all parallel paths:

  • Each approval activity must report its state change immediately to the parent gateway
  • The gateway maintains a state table tracking each path’s current status
  • On any state change, re-evaluate ALL join conditions (both success and failure)
  • First condition to evaluate true takes precedence

This prevents the deadlock where the gateway is waiting for a success condition that can never be met because a failure has already occurred.

Rejection Propagation: Implement proper rejection propagation that handles simultaneous rejections:

  1. When an approval activity transitions to rejected state, it must signal the parent gateway BEFORE completing
  2. The gateway receives the rejection signal and immediately flags all other parallel paths for termination
  3. Other parallel paths check for termination flag before processing their own state changes
  4. If termination flag is set, parallel paths abort their current operation and return control to gateway
  5. Gateway collects all path results and routes to the appropriate rejection handler

The critical piece is the termination flag check - this prevents the race condition where both paths try to propagate rejection simultaneously. The first rejection to reach the gateway wins, and the second rejection is absorbed as part of the coordinated termination.

Workflow Termination: Ensure your workflow has proper cleanup when parallel paths terminate:

  • Define a termination handler at the gateway level that cleans up any active assignments
  • Release all locks held by parallel approval activities
  • Clear any pending notifications or escalations
  • Update workflow state to indicate which path triggered the rejection
  • Log the termination event with details of all parallel path states at termination time

Without proper termination handling, you get orphaned workflow paths that keep the ECO in a “running” state even though no actual progress can occur.

Practical Fix for Your Scenario: For your specific deadlock issue, the root cause is that your join condition only checks for approved status. When both paths reject, neither path meets the join condition, so the gateway waits indefinitely.

Implement this pattern:

  1. Add a workflow variable that tracks rejection count
  2. Each approval activity increments this counter on rejection
  3. Add a gateway condition that checks: if rejection_count > 0, route to rejection handler
  4. This condition should be evaluated BEFORE the success condition
  5. Add automatic path termination when the rejection condition triggers

This ensures that the first rejection (regardless of which path) immediately triggers the failure handling, and the second rejection is handled gracefully as part of the coordinated termination process.

Test this with simultaneous rejections to verify the deadlock is resolved and the workflow properly routes to your rejection handler activity.


This draft is based on general Aras Innovator knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

Your join condition only checks for approved status. You need to handle rejection scenarios explicitly in the gateway configuration. The parallel gateway needs logic that says “if ANY path rejects, route to rejection handler regardless of other path status.” Right now it’s waiting for both paths to approve, which never happens when one or both reject.

That makes sense. So I should add rejection handling to the join condition? Should it be an OR condition like “if design.approved AND mfg.approved then proceed, else if ANY.rejected then route to rejection activity”?

“Tested this on Aras Innovator 12.0 SP9 by adding explicit rejection conditions to the parallel gateway’s synchronization node, which immediately eliminated the deadlock when multiple approvers rejected simultaneously.”

Yes, but you also need to consider the timing. When both paths reject simultaneously, you need proper rejection propagation that can handle race conditions. The workflow engine needs to recognize that once ANY approval path rejects, the entire parallel gateway should immediately terminate the other paths and route to the rejection handler. This prevents the deadlock situation where one path is waiting while the other has already rejected.

I’d also look at your workflow termination settings. When a parallel gateway encounters a rejection, does it properly terminate all active paths before routing to the rejection activity? If not, you can end up with orphaned workflow paths that keep the process in a running state even though it should have moved to rejection handling. Check your gateway’s termination behavior configuration.

The deadlock is definitely a race condition in your parallel gateway. You need to implement a proper rejection handler that takes precedence over the approval join condition. I’ve seen this pattern work well: add a separate rejection path that monitors both approval activities and triggers immediately if either rejects, bypassing the normal join condition logic entirely.