elsa-workflows/elsa-core · error

Workflow instance not found

Error message

Workflow instance not found

What it means

Thrown by BackgroundActivityInvoker.ExecuteAsync when the workflow instance referenced by the scheduled background activity (ScheduledBackgroundActivity.WorkflowInstanceId) cannot be loaded via IWorkflowInstanceManager.FindByIdAsync. The background invoker resumes a bookmarked activity of an existing instance; if the instance row is gone (deleted, pruned by retention, or never existed), it cannot proceed.

Solutions

  1. Check that the workflow instance ID in the scheduled activity exists (workflowInstanceManager.FindByIdAsync or the instances API); if it was deleted intentionally, discard the stale queue message.
  2. Verify the background worker connects to the same database/tenant that owns the instance (connection string / tenant mismatch is common).
  3. Review retention or cleanup jobs: order deletions after all queued background activities for the instance are drained.
  4. Re-run or re-trigger the workflow if the instance was lost and the message is unrecoverable; make queue consumers idempotent for missing instances.

Example fix

// before: blindly queue and resume
await workflowInboxManager.SubmitAsync(new NewWorkflowInboxMessage { ... });

// after: skip resume when the instance no longer exists
var instance = await workflowInstanceManager.FindByIdAsync(instanceId, ct);
if (instance == null)
{
    logger.LogWarning("Skipping background activity for missing instance {InstanceId}", instanceId);
    return;
}
Defensive patterns

Strategy: try-catch

Validate before calling

var instance = await workflowInstanceManager.FindByIdAsync(workflowInstanceId, ct);
if (instance is null)
{
    logger.LogWarning("Background activity for workflow instance {InstanceId} skipped: instance not found.", workflowInstanceId);
    return;
}

Type guard

if (workflowInstance is null) return; // narrow after FindByIdAsync before using instance

Try / catch

try
{
    await backgroundActivityInvoker.ExecuteAsync(scheduledBackgroundActivity, ct);
}
catch (Exception ex) when (ex.Message == "Workflow instance not found")
{
    logger.LogWarning(ex, "Dropping background activity {ActivityId}: instance {InstanceId} no longer exists.",
        scheduledBackgroundActivity.Id, scheduledBackgroundActivity.WorkflowInstanceId);
}

Prevention

When it happens

Trigger: A queued background activity (e.g. from a workflow executor queue such as DispatchWorkflow's background dispatch) executes after the workflow instance was deleted or never persisted; the ID in the message is stale or from another environment/database.

Common situations: Retention/cleanup jobs deleting finished or stale instances while background work is still queued; manually purging instances from the database; running queue messages across environments sharing a queue but not the instance store; crash-recovery replays referencing instances removed during cleanup.

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/154777e3b4d8bcd9. Report an issue: GitHub.

Appendix: source

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

    IBookmarkQueue bookmarkQueue,
    IWorkflowInstanceManager workflowInstanceManager,
    IWorkflowDefinitionService workflowDefinitionService,
    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)

View on GitHub (pinned to fe9217bdfa)