diff --git a/src/modules/Elsa.Scheduling/Activities/Delay.cs b/src/modules/Elsa.Scheduling/Activities/Delay.cs
index 464833214..56dac44cf 100644
--- a/src/modules/Elsa.Scheduling/Activities/Delay.cs
+++ b/src/modules/Elsa.Scheduling/Activities/Delay.cs
@@ -15,7 +15,7 @@ namespace Elsa.Scheduling.Activities;
///
/// Delay execution for the specified amount of time.
///
-[Activity( "Elsa", "Scheduling", "Delay execution for the specified amount of time.")]
+[Activity("Elsa", "Scheduling", "Delay execution for the specified amount of time.")]
public class Delay : Activity, IActivityPropertyDefaultValueProvider
{
///
@@ -67,7 +67,7 @@ public class Delay : Activity, IActivityPropertyDefaultValueProvider
[Input(
Description = "The timespan to delay workflow execution.",
DefaultValueProvider = typeof(Delay)
- )]
+ )]
public Input TimeSpan { get; set; } = default!;
///
@@ -81,35 +81,35 @@ public class Delay : Activity, IActivityPropertyDefaultValueProvider
context.JournalData.Add("ResumeAt", resumeAt);
context.CreateBookmark(payload);
}
-
+
///
/// Creates a new from the specified number of milliseconds.
///
public static Delay FromMilliseconds(
double value,
[CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) => new(System.TimeSpan.FromMilliseconds(value), source, line);
-
+
///
/// Creates a new from the specified number of seconds.
///
public static Delay FromSeconds(
double value,
[CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) => new(System.TimeSpan.FromSeconds(value), source, line);
-
+
///
/// Creates a new from the specified number of minutes.
///
public static Delay FromMinutes(
double value,
[CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) => new(System.TimeSpan.FromMinutes(value), source, line);
-
+
///
/// Creates a new from the specified number of hours.
///
public static Delay FromHours(
double value,
[CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) => new(System.TimeSpan.FromHours(value), source, line);
-
+
///
/// Creates a new from the specified number of days.
///
diff --git a/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.cs b/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.cs
index 74f848603..8e8e5a406 100644
--- a/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.cs
+++ b/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.cs
@@ -530,7 +530,7 @@ public class ActivityExecutionContext : IExecutionContext
///
public void ClearCompletionCallbacks()
{
- var entriesToRemove = WorkflowExecutionContext.CompletionCallbacks.Where(x => x.Owner == this || x.Child.Activity == Activity);
+ var entriesToRemove = WorkflowExecutionContext.CompletionCallbacks.Where(x => x.Owner == this);
WorkflowExecutionContext.RemoveCompletionCallbacks(entriesToRemove);
}
diff --git a/src/modules/Elsa.Workflows.Core/Services/WorkflowExecutionContextMapper.cs b/src/modules/Elsa.Workflows.Core/Services/WorkflowExecutionContextMapper.cs
index ee5f2e82b..2b1df33bf 100644
--- a/src/modules/Elsa.Workflows.Core/Services/WorkflowExecutionContextMapper.cs
+++ b/src/modules/Elsa.Workflows.Core/Services/WorkflowExecutionContextMapper.cs
@@ -65,7 +65,12 @@ public class WorkflowExecutionContextMapper : IWorkflowExecutionContextMapper
foreach (var completionCallbackEntry in state.CompletionCallbacks)
{
var ownerActivityExecutionContext = workflowExecutionContext.ActiveActivityExecutionContexts.First(x => x.Id == completionCallbackEntry.OwnerInstanceId);
- var childNode = workflowExecutionContext.ActiveActivityExecutionContexts.First(x => x.NodeId == completionCallbackEntry.ChildNodeId).ActivityNode;
+ var childNode = workflowExecutionContext.ActiveActivityExecutionContexts.FirstOrDefault(x => x.NodeId == completionCallbackEntry.ChildNodeId)?.ActivityNode;
+
+ // If the child node is null, it means the completion callback was registered for an activity instance that has already completed or was canceled.
+ if(childNode == null)
+ continue;
+
var callbackName = completionCallbackEntry.MethodName;
var callbackDelegate = !string.IsNullOrEmpty(callbackName) ? ownerActivityExecutionContext.Activity.GetActivityCompletionCallback(callbackName) : default;
workflowExecutionContext.AddCompletionCallback(ownerActivityExecutionContext, childNode, callbackDelegate);