elsa-workflows/elsa-core · error · InvalidOperationException

The requested Elsa user does not exist.

Error message

The requested Elsa user does not exist.

What it means

ExternalIdentityUserProvisioningService.ResolveAsync throws this when the caller supplies request.ExistingUserId but no Elsa user with that ID can be found via IUserProvider.FindAsync. The service only links an external identity to an explicitly chosen existing user, and it refuses to silently create one when the given ID is stale or wrong. It indicates a reference to a deleted or never-existing Elsa user.

Solutions

  1. Verify the ExistingUserId value matches a real row in the Elsa user store (check via the admin API or database query on Users).
  2. Remove or regenerate the external identity link so a fresh user is created from the Proposal instead of linking to the stale ID.
  3. Confirm the application connects to the correct database/tenant where the user actually exists.
  4. Re-provision the user: clear the stored external identity mapping and log in again so ResolveAsync creates a new user.

Example fix

// before: stale stored link
request.ExistingUserId = storedLinkId; // deleted user
// after: validate before linking
var user = await userProvider.FindAsync(new() { Id = storedLinkId }, ct);
request.ExistingUserId = user is null ? null : storedLinkId; // fall back to proposal-based creation
Defensive patterns

Strategy: validation

Validate before calling

if (!string.IsNullOrWhiteSpace(request.ExistingUserId))
{
    var user = await userProvider.FindAsync(new() { Id = request.ExistingUserId }, ct);
    if (user is null)
    {
        // stale link — drop it so a fresh user is provisioned from the proposal
        request.ExistingUserId = null;
    }
}

Type guard

bool IsValidExistingUserId(ProvisioningRequest r) => string.IsNullOrWhiteSpace(r.ExistingUserId) || !string.IsNullOrWhiteSpace(r.ExistingUserId); // existence must be checked against the store asynchronously

Try / catch

try
{
    var (user, created) = await provisioning.ResolveAsync(request, ct: ct);
}
catch (InvalidOperationException ex) when (ex.Message == "The requested Elsa user does not exist.")
{
    request.ExistingUserId = null; // re-resolve via proposal path
    var (user, created) = await provisioning.ResolveAsync(request, ct: ct);
}

Prevention

When it happens

Trigger: Calling ResolveAsync (directly or via an external-identity provisioner such as an OIDC/legacy login flow) with a ProvisioningRequest whose ExistingUserId is set to an ID that does not exist in the Elsa user store — e.g. the user was deleted in Elsa while still referenced externally, the ID was truncated/mangled, or the wrong store/tenant database is queried.

Common situations: Re-running provisioning after an admin deleted Elsa users; pointing the app at a fresh/empty database while still carrying old external identity links; copying user IDs between environments; case- or whitespace-corrupted IDs in configuration.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.ExternalAuthentication/Services/ExternalIdentityUserProvisioningService.cs:33

    IUserProvider userProvider,
    IRoleProvider roleProvider,
    IIdentityGenerator identityGenerator)
{
    private const int MaximumUserNameAttempts = 10;

    /// <summary>
    /// Resolves an explicitly selected user or creates a credential-less user from the supplied proposal.
    /// </summary>
    public async ValueTask<(User User, bool WasCreated)> ResolveAsync(
        ProvisioningRequest request,
        Func<string, bool>? tryReserveUserName = null,
        CancellationToken cancellationToken = default)
    {
        if (!string.IsNullOrWhiteSpace(request.ExistingUserId))
        {
            var existingUser = await userProvider.FindAsync(new()
                                   { Id = request.ExistingUserId }, cancellationToken)
                ?? throw new InvalidOperationException("The requested Elsa user does not exist.");
            if (!string.Equals(existingUser.TenantId, request.TenantId, StringComparison.Ordinal))
                throw new InvalidOperationException("The requested Elsa user is outside the target tenant.");

            return (existingUser, false);
        }

        var proposal = request.Proposal ?? throw new InvalidOperationException("A user creation proposal is required for an unlinked external identity.");
        var roleIds = await ResolveRoleIdsAsync(proposal.DefaultRoleIds, cancellationToken);
        var prefix = NormalizeUserNamePrefix(proposal.UserNamePrefix);
        for (var attempt = 0; attempt < MaximumUserNameAttempts; attempt++)
        {
            var name = $"{prefix}-{identityGenerator.GenerateId()}";
            if (tryReserveUserName is not null && !tryReserveUserName(name))
                continue;
            if (await userProvider.FindAsync(new()
                    { Name = name }, cancellationToken) is not null)
                continue;

View on GitHub (pinned to fe9217bdfa)