{"record":{"id":"8a2de56b4f56415d","repo":"elsa-workflows/elsa-core","slug":"target-context-activity-must-be-this-flowchart","errorCode":null,"errorMessage":"Target context activity must be this flowchart","messagePattern":"Target context activity must be this flowchart","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs","lineNumber":125,"sourceCode":"        return rootActivity;\n    }\n\n    private FlowGraph GetFlowGraph(ActivityExecutionContext context)\n    {\n        // Store in TransientProperties so FlowChart is not persisted in WorkflowState \n        return context.TransientProperties.GetOrAdd(GraphTransientProperty, () => new FlowGraph(Connections, GetStartActivity(context)));\n    }\n\n    private FlowScope GetFlowScope(ActivityExecutionContext context)\n    {\n        return context.GetProperty(ScopeProperty, () => new FlowScope());\n    }\n\n    private async ValueTask ProcessChildCompletedAsync(ActivityExecutionContext flowchartContext, IActivity completedActivity, ActivityExecutionContext completedActivityContext, Outcomes outcomes)\n    {\n        if (flowchartContext.Activity != this)\n        {\n            throw new(\"Target context activity must be this flowchart\");\n        }\n\n        // If the completed activity's status is anything but \"Completed\", do not schedule its outbound activities.\n        if (completedActivityContext.Status != ActivityStatus.Completed)\n        {\n            return;\n        }\n\n        // If the complete activity is a terminal node, complete the flowchart immediately.\n        if (completedActivity is ITerminalNode)\n        {\n            await flowchartContext.CompleteActivityAsync();\n            return;\n        }\n\n        // Schedule the outbound activities\n        var flowGraph = GetFlowGraph(flowchartContext);\n        var flowScope = GetFlowScope(flowchartContext);","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs#L107-L143","documentation":"ProcessChildCompletedAsync is a completion callback that must be invoked with an ActivityExecutionContext whose Activity is the Flowchart instance itself. If the context belongs to a different activity, the internal counter/bookkeeping state would be corrupted, so the code throws an InvalidOperationException immediately. This is an internal invariant check, not a user-facing validation.","triggerScenarios":"A child activity's Completed/CompletedCallback resolves to the ProcessChildCompletedAsync handler while the callback context was captured for a different activity; typically caused by custom Flowchart subclasses or reused delegates wiring OnChildCompletedCounterBasedLogicAsync to the wrong ActivityExecutionContext.","commonSituations":"Custom flowchart-like composite activities copying Elsa's Flowchart sample code but passing the wrong execution context to the completion callback; version drift where Flowchart internals changed but derived classes call the private handler directly via reflection.","solutions":["Ensure the completion callback is registered on the flowchart's own ActivityExecutionContext, not a child's.","If subclassing Flowchart, call the public/protected scheduling APIs instead of invoking the private handler with a foreign context.","Re-check that activities are scheduled with scheduleWorkOptions tied to the flowchart context.","Update Elsa packages together (core and flows) if a mixed-version runtime mismatches callback contexts."],"exampleFix":"// before\nscheduleWorkOptions = new() { CompletionCallback = OnChildCompletedAsync }; // callback captures child context\n// after\nflowchartContext.ScheduleActivity(activity, OnChildCompletedAsync); // Elsa binds the flowchart context as the first parameter","handlingStrategy":"type-guard","validationCode":"if (context.Activity is not Flowchart) throw new InvalidOperationException(\"Completion callback must be bound to the Flowchart context.\");","typeGuard":"static bool IsFlowchartContext(ActivityExecutionContext ctx) => ctx.Activity is Flowchart;","tryCatchPattern":"try { await ProcessChildCompletedAsync(flowchartContext, completedActivity, completedActivityContext, outcomes); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Target context activity must be this flowchart\")\n{\n    logger.LogError(ex, \"Flowchart completion callback invoked with mismatched activity context.\");\n}","preventionTips":["Always schedule child activities through the flowchart's ActivityExecutionContext so completion callbacks bind correctly.","Do not reuse flowchart completion delegates for other composite activities.","Keep Elsa.Workflows.Core packages on a single version across the app."],"tags":["flowchart","internal-invariant","workflow-engine"],"backgroundTag":"internal-invariant-violation","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}