elsa-workflows/elsa-core · error · InvalidOperationException
WorkflowExecutionContext not found. This value exists only…
Error message
WorkflowExecutionContext not found. This value exists only on activity execution contexts.
What it means
An InvalidOperationException thrown by GetWorkflowExecutionContext when the ExpressionExecutionContext's TransientProperties dictionary does not contain the WorkflowExecutionContext key. WorkflowExecutionContext is only attached to transient properties when an expression is evaluated within an activity execution; standalone evaluations lack it.
Solutions
- Only call this inside code that runs during activity execution, where TransientProperties is populated.
- Use TryGetValue on context.TransientProperties with the WorkflowExecutionContextKey to test presence first.
- Pass the WorkflowExecutionContext explicitly to your evaluation code instead of pulling it from the expression context.
- In tests, populate TransientProperties[WorkflowExecutionContextKey] with a real or stubbed context.
Example fix
// before
var workflowExecutionContext = context.GetWorkflowExecutionContext(); // throws outside activity execution
// after
if (context.TransientProperties.TryGetValue(WorkflowExecutionContextKey, out var value) && value is WorkflowExecutionContext wfCtx)
{
// use wfCtx
} Defensive patterns
Strategy: type-guard
Validate before calling
var hasWorkflowContext = expressionContext.TransientProperties.ContainsKey(WorkflowExecutionContextKey);
Type guard
bool TryGetWorkflowExecutionContext(ExpressionExecutionContext ctx, out WorkflowExecutionContext? wfCtx)
=> ctx.TransientProperties.TryGetValue(WorkflowExecutionContextKey, out var v) && (wfCtx = v as WorkflowExecutionContext) is not null; Try / catch
catch (InvalidOperationException ex) when (ex.Message.StartsWith("WorkflowExecutionContext not found"))
{
// fall back to explicit context passing
} Prevention
- Only evaluate expressions inside activity execution.
- Pass WorkflowExecutionContext explicitly in custom evaluators.
- Use TryGetValue patterns instead of throwing getters in library extensions.
When it happens
Trigger: Calling GetWorkflowExecutionContext() on an ExpressionExecutionContext created outside activity execution - e.g., evaluating an expression at design time, in a workflow-level (not activity-level) context, or via a custom evaluator that did not populate TransientProperties.
Common situations: Custom expression syntax/plugins that evaluate expressions without the normal activity pipeline; designer-time evaluation/preview; background jobs evaluating stored expressions without a running workflow; unit tests constructing bare ExpressionExecutionContexts.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Output conversion failed during result validation
- Activity type not found
- Activity descriptor not found
- No input with name could be found
- Failed to evaluate activity input
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/29fdebae1790e398.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs:82
[InputKey] = input
};
/// <param name="context">The context to start searching from.</param>
extension(ExpressionExecutionContext context)
{
/// <summary>
/// Returns the <see cref="Workflow"/> of the specified <see cref="ExpressionExecutionContext"/>
/// </summary>
public bool TryGetWorkflowExecutionContext(out WorkflowExecutionContext workflowExecutionContext) => context.TransientProperties.TryGetValue(WorkflowExecutionContextKey, out workflowExecutionContext!);
/// <summary>
/// Returns the <see cref="WorkflowExecutionContext"/> of the specified <see cref="ExpressionExecutionContext"/>
/// </summary>
public WorkflowExecutionContext GetWorkflowExecutionContext()
{
return context.TransientProperties.TryGetValue(WorkflowExecutionContextKey, out var value)
? (WorkflowExecutionContext)value
: throw new InvalidOperationException("WorkflowExecutionContext not found. This value exists only on activity execution contexts.");
}
/// <summary>
/// Returns the <see cref="ActivityExecutionContext"/> of the specified <see cref="ExpressionExecutionContext"/>
/// </summary>
public ActivityExecutionContext GetActivityExecutionContext()
{
return context.TransientProperties.TryGetValue(ActivityExecutionContextKey, out var value)
? (ActivityExecutionContext)value
: throw new InvalidOperationException("ActivityExecutionContext not found. This value exists only on activity execution contexts.");
}
/// <summary>
/// Returns the <see cref="ActivityExecutionContext"/> of the specified <see cref="ExpressionExecutionContext"/>
/// </summary>
public bool TryGetActivityExecutionContext(out ActivityExecutionContext activityExecutionContext) => context.TransientProperties.TryGetValue(ActivityExecutionContextKey, out activityExecutionContext!);
/// <summary>View on GitHub (pinned to fe9217bdfa)