{"record":{"id":"25f9798e614744b7","repo":"elsa-workflows/elsa-core","slug":"unsupported-flowjoinmode-mode","errorCode":null,"errorMessage":"Unsupported FlowJoinMode: {mode}","messagePattern":"Unsupported FlowJoinMode: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs","lineNumber":261,"sourceCode":"        {\n            // Implicit join case - treat as WaitAllActive\n            return FlowJoinMode.WaitAllActive;\n        }\n    }\n\n    /// <summary>\n    /// Schedules a join activity based on inbound connection statuses.\n    /// </summary>\n    private static async ValueTask<bool> MaybeScheduleOutboundActivityAsync(FlowGraph flowGraph, FlowScope flowScope, ActivityExecutionContext flowchartContext, ActivityExecutionContext? completedActivityContext, Connection outboundConnection, IActivity outboundActivity, ActivityCompletionCallback completionCallback)\n    {\n        FlowJoinMode mode = await GetMergeModeAsync(flowchartContext, outboundActivity);\n\n        return mode switch\n        {\n            FlowJoinMode.WaitAll => await MaybeScheduleWaitAllActivityAsync(flowGraph, flowScope, flowchartContext, completedActivityContext, outboundActivity, completionCallback),\n            FlowJoinMode.WaitAllActive => await MaybeScheduleWaitAllActiveActivityAsync(flowGraph, flowScope, flowchartContext, completedActivityContext, outboundActivity, completionCallback),\n            FlowJoinMode.WaitAny => await MaybeScheduleWaitAnyActivityAsync(flowGraph, flowScope, flowchartContext, completedActivityContext, outboundConnection, outboundActivity, completionCallback),\n            _ => throw new($\"Unsupported FlowJoinMode: {mode}\"),\n        };\n    }\n\n    /// <summary>\n    /// Determines whether to schedule an activity based on the FlowJoinMode.WaitAll behavior.\n    /// If all inbound connections were visited, it checks if they were all followed to decide whether to schedule or skip the activity.\n    /// </summary>\n    private static async ValueTask<bool> MaybeScheduleWaitAllActivityAsync(FlowGraph flowGraph, FlowScope flowScope, ActivityExecutionContext flowchartContext, ActivityExecutionContext? completedActivityContext, IActivity outboundActivity, ActivityCompletionCallback completionCallback)\n    {\n        if (!flowScope.AllInboundConnectionsVisited(flowGraph, outboundActivity))\n            // Not all inbound connections have been visited yet; do not schedule anything yet.\n            return false;\n\n        if (flowScope.AllInboundConnectionsFollowed(flowGraph, outboundActivity))\n            // All inbound connections were followed; schedule the outbound activity.\n            return await ScheduleOutboundActivityAsync(flowchartContext, completedActivityContext, outboundActivity, completionCallback);\n        else\n            // No inbound connections were followed; skip the outbound activity.","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs#L243-L279","documentation":"Flowchart join behavior is selected via the FlowJoinMode enum (WaitAll, WaitAllActive, WaitAny). When scheduling an outbound activity after a completion, MaybeScheduleOutboundActivityAsync switches on the joined activity's FlowJoin mode; an unknown or out-of-range value hits the discard arm and throws InvalidOperationException. This protects against silently applying wrong join semantics.","triggerScenarios":"A FlowJoin activity (or the flowchart's join resolution) has a Mode value not present in the FlowJoinMode enum — e.g. an enum cast from an int that has no named member, a stale serialized mode from an older Elsa version, or default(FlowJoinMode) when 0 is not a defined member.","commonSituations":"Upgrading workflows authored on a version whose enum members were renamed/removed; deserializing definitions from JSON where the mode string failed to map; custom code casting raw integers into FlowJoinMode.","solutions":["Set the join activity's Mode to a valid FlowJoinMode value: WaitAll, WaitAllActive, or WaitAny.","Migrate workflow definitions from removed enum members to the current FlowJoinMode set.","Avoid casting arbitrary ints to FlowJoinMode; parse with Enum.TryParse and validate.","Catch the exception during scheduling and fall back to a default join mode if configurations are untrusted."],"exampleFix":"// before\nvar join = new FlowJoin { Mode = (FlowJoinMode)7 };\n// after\nvar join = new FlowJoin { Mode = Enum.IsDefined(typeof(FlowJoinMode), mode) ? (FlowJoinMode)mode : FlowJoinMode.WaitAny };","handlingStrategy":"validation","validationCode":"if (!Enum.IsDefined(typeof(FlowJoinMode), join.Mode))\n    throw new InvalidOperationException($\"Join '{join.Id}' has unsupported FlowJoinMode '{join.Mode}'.\");","typeGuard":"static bool IsValidJoinMode(FlowJoinMode mode) => mode is FlowJoinMode.WaitAll or FlowJoinMode.WaitAllActive or FlowJoinMode.WaitAny;","tryCatchPattern":"try { await MaybeScheduleOutboundActivityAsync(...); }\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Unsupported FlowJoinMode:\"))\n{\n    logger.LogError(ex, \"Workflow uses an unknown join mode; migrate the definition.\");\n}","preventionTips":["Only assign named FlowJoinMode members, never raw integer casts.","Migrate definitions when upgrading Elsa versions if enum members changed.","Validate join modes at workflow import time."],"tags":["flowchart","enum","join-mode","workflow-engine"],"backgroundTag":"invalid-enum-value","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"}