elsa-workflows/elsa-core · error

Workflow definition not found

Error message

Workflow definition not found

What it means

Thrown by BackgroundActivityInvoker.ExecuteAsync when the workflow instance was found but its definition graph cannot be resolved: workflowDefinitionService.FindWorkflowGraphAsync(workflowInstance.DefinitionVersionId) returned null. The instance's DefinitionVersionId no longer resolves to a workflow graph, so the background activity cannot be resumed.

Solutions

  1. Verify the definition referenced by workflowInstance.DefinitionVersionId exists in the same store/tenant the runtime reads from; restore or re-import it if deleted.
  2. Check host configuration: all required workflow definition providers/features (e.g. management feature, definition store) are registered so FindWorkflowGraphAsync can resolve the ID.
  3. Confirm the worker uses the same database/connection and tenant as the environment that created the instance.
  4. If the definition is unrecoverable, terminate/cancel the stale instances and drop their queued background activities instead of resuming them.

Example fix

// before: assuming definitions are always present
var workflow = await workflowDefinitionService.FindWorkflowGraphAsync(instance.DefinitionVersionId, ct);

// after: keep definitions and instances together; guard before scheduling background work
var graph = await workflowDefinitionService.FindWorkflowGraphAsync(instance.DefinitionVersionId, ct);
if (graph == null)
    throw new InvalidOperationException($"Definition {instance.DefinitionVersionId} missing for instance {instance.Id}; restore the definition before resuming.");
Defensive patterns

Strategy: try-catch

Validate before calling

var graph = await workflowDefinitionService.FindWorkflowGraphAsync(workflowInstance.DefinitionVersionId, ct);
if (graph is null)
{
    logger.LogWarning("Definition {DefinitionVersionId} for instance {InstanceId} is missing; cannot resume background activity.",
        workflowInstance.DefinitionVersionId, workflowInstance.Id);
    return;
}

Type guard

if (workflow is null) throw new InvalidOperationException($"Definition {workflowInstance.DefinitionVersionId} not resolvable for instance {workflowInstance.Id}.");

Try / catch

try
{
    await backgroundActivityInvoker.ExecuteAsync(scheduledBackgroundActivity, ct);
}
catch (Exception ex) when (ex.Message == "Workflow definition not found")
{
    logger.LogWarning(ex, "Cannot resume background activity {ActivityId}: definition {DefinitionVersionId} is unavailable.",
        scheduledBackgroundActivity.Id, definitionVersionId);
}

Prevention

When it happens

Trigger: The workflow definition (or the specific version) referenced by the stored instance's DefinitionVersionId was deleted; the definition service/provider backing the lookup is not registered or points at a different store; the definition ID stored on the instance is from another environment.

Common situations: Deleting or re-importing workflow definitions while instances are still running; database/tenant mismatch between the instance store and the definition store; missing workflow definition provider registration in the host; staging data copied partially (instances without their definitions).

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.Workflows.Runtime/Services/BackgroundActivityInvoker.cs:34

    IVariablePersistenceManager variablePersistenceManager,
    IActivityInvoker activityInvoker,
    IActivityPropertyLogPersistenceEvaluator activityPropertyLogPersistenceEvaluator,
    WorkflowHeartbeatGeneratorFactory workflowHeartbeatGeneratorFactory,
    IServiceProvider serviceProvider,
    ILogger<BackgroundActivityInvoker> logger)
    : IBackgroundActivityInvoker
{
    private readonly ILogger _logger = logger;

    /// <inheritdoc />
    public async Task ExecuteAsync(ScheduledBackgroundActivity scheduledBackgroundActivity, CancellationToken cancellationToken = default)
    {
        var workflowInstanceId = scheduledBackgroundActivity.WorkflowInstanceId;
        var workflowInstance = await workflowInstanceManager.FindByIdAsync(workflowInstanceId, cancellationToken);
        if (workflowInstance == null) throw new("Workflow instance not found");
        var workflowState = workflowInstance.WorkflowState;
        var workflow = await workflowDefinitionService.FindWorkflowGraphAsync(workflowInstance.DefinitionVersionId, cancellationToken);
        if (workflow == null) throw new("Workflow definition not found");
        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(serviceProvider, workflow, workflowState, cancellationToken: cancellationToken);
        var activityNodeId = scheduledBackgroundActivity.ActivityNodeId;
        var activityExecutionContext = workflowExecutionContext.ActivityExecutionContexts.First(x => x.NodeId == activityNodeId);

        using (workflowHeartbeatGeneratorFactory.CreateHeartbeatGenerator(workflowExecutionContext))
        {
            await variablePersistenceManager.LoadVariablesAsync(workflowExecutionContext);
            activityExecutionContext.SetIsBackgroundExecution();
            await activityInvoker.InvokeAsync(activityExecutionContext);
            await variablePersistenceManager.SaveVariablesAsync(workflowExecutionContext);
        }
        await ResumeWorkflowAsync(activityExecutionContext, scheduledBackgroundActivity);
    }

    private async Task ResumeWorkflowAsync(ActivityExecutionContext activityExecutionContext, ScheduledBackgroundActivity scheduledBackgroundActivity)
    {
        var cancellationToken = activityExecutionContext.CancellationToken;
        var activityNodeId = scheduledBackgroundActivity.ActivityNodeId;

View on GitHub (pinned to fe9217bdfa)