{"record":{"id":"5099387f1bcb37ea","repo":"elsa-workflows/elsa-core","slug":"statemachine-transitions-cannot-share-a-trigger-activity-in","errorCode":null,"errorMessage":"StateMachine transitions cannot share a Trigger activity in Elsa 3.8. Give each transition its own trigger activity with a unique ID.","messagePattern":"StateMachine transitions cannot share a Trigger activity in Elsa 3\\.8\\. Give each transition its own trigger activity with a unique ID\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Workflows.Core/Activities/StateMachine/Activities/StateMachine.cs","lineNumber":326,"sourceCode":"                yield return transition.Action;\n        }\n\n        yield return _automaticTransitionContinuation;\n    }\n\n    private void EnsureSupportedTriggerIdentities()\n    {\n        var triggers = Transitions.Where(x => x.Trigger != null).Select(x => x.Trigger!).ToList();\n        var seenInstances = new HashSet<IActivity>(ReferenceEqualityComparer.Instance);\n        var seenIds = new HashSet<string>(StringComparer.Ordinal);\n\n        foreach (var trigger in triggers)\n        {\n            var sharesInstance = !seenInstances.Add(trigger);\n            var duplicatesId = !string.IsNullOrWhiteSpace(trigger.Id) && !seenIds.Add(trigger.Id);\n\n            if (sharesInstance || duplicatesId)\n                throw new InvalidOperationException(\"StateMachine transitions cannot share a Trigger activity in Elsa 3.8. Give each transition its own trigger activity with a unique ID.\");\n        }\n    }\n\n    private void SetCurrentState(ActivityExecutionContext context, string? state)\n    {\n        CurrentState = state;\n\n        if (state == null)\n            context.RemoveProperty(CurrentStateProperty);\n        else\n            context.SetProperty(CurrentStateProperty, state);\n    }\n\n    private bool IsCurrentSource(ActivityExecutionContext context, Transition transition) => string.Equals(transition.From, GetCurrentState(context), StringComparison.Ordinal);\n\n    private static async Task<bool> EvaluateConditionAsync(ActivityExecutionContext context, Input<bool> condition)\n    {\n        var evaluator = context.GetRequiredService<IExpressionEvaluator>();","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Workflows.Core/Activities/StateMachine/Activities/StateMachine.cs#L308-L344","documentation":"StateMachine.EnsureSupportedTriggerIdentities throws InvalidOperationException when two or more transitions reference the same trigger activity instance or two triggers share the same non-empty Id. Elsa 3.8 requires each transition to have its own uniquely-identified trigger so trigger/bookmark bookkeeping stays unambiguous. Validated during ExecuteAsync.","triggerScenarios":"Defining a StateMachine where multiple transitions reuse one trigger activity instance, or where two trigger activities share the same Id string; validated when the state machine executes.","commonSituations":"Reusing a single trigger variable across several transitions for convenience; copying transitions in the designer which duplicates trigger Ids; programmatic construction loops that reuse a shared trigger object.","solutions":["Give each transition its own trigger activity instance with a unique Id.","If multiple transitions should react to the same event, create separate trigger instances (one per transition).","De-duplicate trigger Ids across transitions in the state machine definition.","When building state machines in code, construct a new trigger inside the loop instead of reusing a captured variable."],"exampleFix":"// before\nvar trigger = new EventTrigger(\"OrderReceived\") { Id = \"t1\" };\ntransitions.Add(new Transition { Trigger = trigger });\ntransitions.Add(new Transition { Trigger = trigger }); // shared instance -> throws\n// after\ntransitions.Add(new Transition { Trigger = new EventTrigger(\"OrderReceived\") { Id = \"t1\" } });\ntransitions.Add(new Transition { Trigger = new EventTrigger(\"OrderReceived\") { Id = \"t2\" } });","handlingStrategy":"validation","validationCode":"// before execution, check trigger uniqueness across transitions\nvar triggerIds = stateMachine.Transitions.Select(t => t.Trigger.Id).Where(id => !string.IsNullOrWhiteSpace(id)).ToList();\nif (triggerIds.Count != triggerIds.Distinct().Count())\n    throw new InvalidOperationException(\"State machine transitions must use unique trigger Ids.\");","typeGuard":"static bool HasUniqueTriggers(StateMachine sm)\n{\n    var seen = new HashSet<object?>();\n    var ids = new HashSet<string>();\n    foreach (var t in sm.Transitions)\n    {\n        if (!seen.Add(t.Trigger)) return false;\n        if (!string.IsNullOrWhiteSpace(t.Trigger.Id) && !ids.Add(t.Trigger.Id)) return false;\n    }\n    return true;\n}","tryCatchPattern":"try { await workflowRunner.RunAsync(stateMachineWorkflow); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"cannot share a Trigger activity\"))\n{\n    logger.LogError(ex, \"State machine has duplicate trigger instances or Ids\");\n}","preventionTips":["Construct a fresh trigger instance per transition when building state machines in code.","Check the designer for duplicated trigger Ids after copy/paste of transitions.","Add a definition validation step that asserts trigger instance/Id uniqueness."],"tags":["workflow","statemachine","validation","duplicate"],"backgroundTag":"invalid-state-transition","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}