elsa-workflows/elsa-core · critical · Exception
We lost a context. This could indicate a bug in a parent…
Error message
We lost a context. This could indicate a bug in a parent activity that completed before (some of) its child activities.
What it means
While extracting the state of active activity execution contexts, the extractor records each context's parent ID and verifies the parent still exists in the workflow execution context's collection. A missing parent means a parent activity's context was completed/removed while its child contexts remained active — an inconsistency that would produce unrestorable state — so the extractor throws with this diagnostic message.
Solutions
- Fix the offending parent activity to remain active until every child activityExecutionContext completes (defer completion until all children's callbacks/contexts are done).
- Update to the latest Elsa packages; several parent-completes-too-early bugs in built-in activities have been patched.
- Review custom activities for early context.Complete()/broken completion-callback wiring and use context.DeferCallbacks where children are scheduled.
- Identify the guilty activity from the exception context/logs and restructure the workflow (e.g. use a Parallel/Flowchart with correct completion semantics).
- If persisting mid-execution, ensure extraction happens only at safe suspension points where parent/child contexts are consistent.
Example fix
// before (parent activity ExecuteAsync)
foreach (var child in children) context.ScheduleActivity(child);
context.Complete(); // parent context dies before children -> lost parent
// after
foreach (var child in children)
context.ScheduleActivity(child, completionCallback: _ =>
{
if (context.GetActivityExecutionContextCount() == 0) // or track pending children
context.Complete();
}); Defensive patterns
Strategy: try-catch
Validate before calling
var activeIds = context.GetActiveActivityExecutionContexts().Select(x => x.Id).ToHashSet(); bool parentsConsistent = context.GetActiveActivityExecutionContexts().All(x => x.ParentContext == null || activeIds.Contains(x.ParentContext.Id));
Try / catch
try { var state = extractor.Extract(context); } catch (Exception ex) { logger.LogCritical(ex, "State extraction failed: parent activity completed before children (workflow {InstanceId})", context.Id); throw; } Prevention
- Never call Complete() on a parent activity before all child completion callbacks run
- Use DeferCallbacks when scheduling children whose completion must precede parent completion
- Keep Elsa packages updated; several parent-completion bugs are fixed in newer releases
- Test suspend/resume of workflows containing composites and parallel activities
When it happens
Trigger: Extract/persist/suspend a workflow instance when an active ActivityExecutionContext references a ParentContext ID that is no longer present in WorkflowExecutionContext.ActivityExecutionContexts — typically a parent activity completed before some of its children.
Common situations: Buggy custom or composite activities calling Complete() before all child contexts finished; race between parent completion and child scheduling; older Elsa versions with known parent-completion bugs in parallel/flow activities; resuming after partial state corruption.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Lost an owner context
- C# workflow expression execution is disabled. Set…
- Failed to deserialize
- Type does not expose an Add method for .
- Failed to convert an object of type
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/41659f55105e73e6.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs:301
}
var completionCallbacks = workflowExecutionContext.CompletionCallbacks.Select(x => new CompletionCallbackState(x.Owner.Id, x.Child.NodeId, x.CompletionCallback?.Method.Name, x.Tag));
state.CompletionCallbacks = completionCallbacks.ToList();
}
private static void ExtractActiveActivityExecutionContexts(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
{
ActivityExecutionContextState CreateActivityExecutionContextState(ActivityExecutionContext activityExecutionContext)
{
var parentId = activityExecutionContext.ParentActivityExecutionContext?.Id;
if (parentId != null)
{
var parentContext = activityExecutionContext.WorkflowExecutionContext.ActivityExecutionContexts.FirstOrDefault(x => x.Id == parentId);
if (parentContext == null)
throw new("We lost a context. This could indicate a bug in a parent activity that completed before (some of) its child activities.");
}
var activityExecutionContextState = new ActivityExecutionContextState
{
Id = activityExecutionContext.Id,
CallStackDepth = activityExecutionContext.CallStackDepth,
ParentContextId = activityExecutionContext.ParentActivityExecutionContext?.Id,
ScheduledActivityNodeId = activityExecutionContext.NodeId,
OwnerActivityNodeId = activityExecutionContext.ParentActivityExecutionContext?.NodeId,
Properties = activityExecutionContext.Properties,
Metadata = activityExecutionContext.Metadata,
ActivityState = activityExecutionContext.ActivityState,
Status = activityExecutionContext.Status,
IsExecuting = activityExecutionContext.IsExecuting,
FaultCount = activityExecutionContext.AggregateFaultCount,
StartedAt = activityExecutionContext.StartedAt,
CompletedAt = activityExecutionContext.CompletedAt,
Tag = activityExecutionContext.Tag,View on GitHub (pinned to fe9217bdfa)