elsa-workflows/elsa-core · error · FaultException

AlterationFaultCodes.PlanNotFound

AlterationFaultCodes.PlanNotFound

Error message

Alteration Plan with ID {planId} not found.

What it means

The CompleteAlterationPlan activity looks up the alteration plan by its PlanId input via IAlterationPlanManager.GetPlanAsync and throws a FaultException with code AlterationFaultCodes.PlanNotFound when no plan exists. This is a modeled workflow fault (category Alteration, type System) so the workflow can catch and compensate it rather than crashing the host.

Solutions

  1. Verify the PlanId input value matches an existing alteration plan ID in the store.
  2. Confirm the runtime is connected to the same tenant/database where the plan was created.
  3. Add a fault handler for AlterationFaultCodes.PlanNotFound on the activity/workflow to fail gracefully.
  4. Check that the plan was not deleted by a concurrent process before completion.

Example fix

// before
context.Set(PlanId, planIdFromExternalSystem);
// (no check that planId exists)

// after
var plan = await manager.GetPlanAsync(planIdFromExternalSystem, ct);
if (plan == null)
    throw new InvalidOperationException($"Plan {planIdFromExternalSystem} does not exist; check the PlanId input.");
context.Set(PlanId, planIdFromExternalSystem);
Defensive patterns

Strategy: try-catch

Validate before calling

var plan = await manager.GetPlanAsync(planId, ct);
if (plan is null)
    throw new InvalidOperationException($"Plan '{planId}' not found; fix the PlanId input before running the workflow.");

Type guard

bool PlanExists(IAlterationPlan? plan) => plan is not null;

Try / catch

try
{
    await workflow.RunAsync(instance, ct);
}
catch (FaultException ex) when (ex.Code == AlterationFaultCodes.PlanNotFound)
{
    logger.LogError("Alteration plan not found: {Message}", ex.Message);
}

Prevention

When it happens

Trigger: Executing a CompleteAlterationPlan activity whose PlanId input references an ID that does not exist (deleted plan, wrong ID input, plan stored in a different tenant/database).

Common situations: Plan ID passed via workflow input from an external system with a typo; plan deleted between dispatch and completion; multi-tenant deployment where the plan lives under another tenant.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.Alterations/Activities/CompleteAlterationPlan.cs:44

    public CompleteAlterationPlan([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
    {
    }

    /// <summary>
    /// The ID of the alteration plan.
    /// </summary>
    public Input<string> PlanId { get; set; } = null!;

    /// <inheritdoc />
    protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
    {
        var cancellationToken = context.CancellationToken;
        var planId = context.Get(PlanId)!;
        var manager = context.GetRequiredService<IAlterationPlanManager>();
        var plan = await manager.GetPlanAsync(planId, cancellationToken);

        if (plan == null)
            throw new FaultException(AlterationFaultCodes.PlanNotFound, AlterationFaultCategories.Alteration, DefaultFaultTypes.System, $"Alteration Plan with ID {planId} not found.");

        await manager.CompletePlanAsync(plan, cancellationToken);
    }
}

View on GitHub (pinned to fe9217bdfa)