elsa-workflows/elsa-core · critical · Exception

Lost an owner context

Error message

Lost an owner context

What it means

During workflow state extraction, WorkflowStateExtractor serializes all completion callbacks, each of which must reference an owner ActivityExecutionContext that is currently active. If a callback's owner is no longer among the active contexts, internal bookkeeping is inconsistent (the owner was completed/cleared without removing its callback), so the extractor throws rather than persisting corrupt state.

Solutions

  1. Fix the parent activity to keep itself active until all scheduled children invoke their completion callbacks (use Complete() only after callbacks fire, or use ScheduleActivity with correct delegate/complete flags).
  2. Ensure completion callbacks are removed when their owner context completes (clear callbacks in the owner's completion path).
  3. Check custom activities for calls to Complete() before all child callbacks execute — use context.DeferCallbacks or wait for pending children.
  4. Update Elsa: known parent-completion bugs in bundled activities have been fixed in newer versions.
  5. If a third-party activity triggers it, report/replace it; workaround by restructuring the workflow so the parent remains active.

Example fix

// before (custom parent activity)
ScheduleChildren(context);
context.Complete(); // completes while children still pending -> lost owner context
// after
ScheduleChildren(context);
context.DeferCallbacks(); // keep context active until child completion callbacks run, then Complete()
Defensive patterns

Strategy: fallback

When it happens

Trigger: Extract (persistence or suspension) while workflowExecutionContext.CompletionCallbacks contains a callback whose Owner is not in GetActiveActivityExecutionContexts() — i.e. an owner context completed or was removed but its child completion callback remained registered.

Common situations: A parent activity completed while children it scheduled were still pending (parent completed without awaiting all children); custom activities registering completion callbacks incorrectly; bugs in composite/parallel activity implementations; state extraction racing with context cleanup.

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


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/93d5a89696be1d5a. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Workflows.Core/Services/WorkflowStateExtractor.cs:282

                existingActivityExecutionContext,
                input,
                activityWorkItemState.SchedulingActivityExecutionId,
                activityWorkItemState.SchedulingWorkflowInstanceId,
                activityWorkItemState.SchedulingCallStackDepth);
            workflowExecutionContext.Scheduler.Schedule(workItem);
        }
    }

    private static void ExtractCompletionCallbacks(WorkflowState state, WorkflowExecutionContext workflowExecutionContext)
    {
        // Assert that all referenced owner contexts exist.
        var activeContexts = workflowExecutionContext.GetActiveActivityExecutionContexts().ToList();
        foreach (var completionCallback in workflowExecutionContext.CompletionCallbacks)
        {
            var ownerContext = activeContexts.FirstOrDefault(x => x == completionCallback.Owner);

            if (ownerContext == null)
                throw new("Lost an owner context");
        }

        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)

View on GitHub (pinned to fe9217bdfa)