elsa-workflows/elsa-core · error · InvalidOperationException

The configured secret binding could not be resolved.

Error message

The configured secret binding could not be resolved.

What it means

ResolveAsync throws when the secret manager has no secret stored under the binding's Reference. A SecretBinding is only a pointer; if the underlying managed secret was deleted, never created, or the reference is stale, resolution cannot proceed.

Solutions

  1. Re-stage the secret material via StageAsync and republish a fresh binding
  2. Delete/recreate the binding so it points to an existing secret
  3. Verify the secret store contains an entry for binding.Reference (migrate secrets if restoring from backup)

Example fix

// before
var resolved = await resolver.ResolveAsync(staleBinding);
// after
var state = await resolver.GetStateAsync(staleBinding);
if (state.SecretExists) {
    var resolved = await resolver.ResolveAsync(staleBinding);
} else {
    var fresh = await resolver.StageAsync(new ManagedSecretBindingWriteRequest { ConnectionId = staleBinding.ConnectionId, FieldName = "clientSecret" });
    // publish and use fresh binding
}
Defensive patterns

Strategy: try-catch

Validate before calling

var state = await resolver.GetStateAsync(binding); // surface absence to the user before resolving

Type guard

bool IsResolvable(SecretBinding b) => b.Reference is { } r && !string.IsNullOrWhiteSpace(r);

Try / catch

try { return await resolver.ResolveAsync(binding); }
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be resolved"))
{ throw new ConfigurationException("Secret binding reference no longer exists; re-enter the secret.", ex); }

Prevention

When it happens

Trigger: Calling ResolveAsync with a binding whose Reference does not exist in the secret manager: the secret was deleted (e.g. via RemoveAsync or CAS-failure cleanup), the binding was persisted/serialized from another environment, or the reference GUID is fabricated.

Common situations: Restoring workflow definitions or connection configs from a backup into a fresh database where secrets were not migrated; deleting secrets while old bindings still reference them; copying configs between dev/prod environments.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.ExternalAuthentication.Secrets/Services/ElsaSecretBindingResolver.cs:71

    {
        EnsureResolverType(binding);
        var secret = await secretManager.GetAsync(binding.Reference, cancellationToken);
        if (secret is null)
            return new(false, false);

        var configured = secret is { Status: SecretStatus.Active, LatestActiveVersion: not null };
        if (!configured || !IsCompatible(secret, binding))
            return new(configured, false);

        var test = await secretManager.TestAsync(secret.Name, cancellationToken);
        return new(true, test.Succeeded);
    }

    public async ValueTask<ResolvedSecretBinding> ResolveAsync(SecretBinding binding, CancellationToken cancellationToken = default)
    {
        EnsureResolverType(binding);
        var secret = await secretManager.GetAsync(binding.Reference, cancellationToken)
            ?? throw new InvalidOperationException("The configured secret binding could not be resolved.");
        if (!IsCompatible(secret, binding))
            throw new InvalidOperationException("The configured secret binding is incompatible with the required type or scope.");
        if (secret is not { Status: SecretStatus.Active, LatestActiveVersion: { } version })
            throw new InvalidOperationException("The configured secret binding is not active.");

        var payload = await secretManager.ResolvePayloadAsync(secret, cancellationToken);
        if (payload.Value is null)
            throw new InvalidOperationException("The configured secret binding could not be resolved.");

        var fingerprint = handleHasher.Hash($"{ResolverType}:{secret.Id}:{version.Version}:{version.CreatedAt.ToUnixTimeMilliseconds()}");
        return new(new(payload.Value), fingerprint);
    }

    private static void EnsureResolverType(SecretBinding binding)
    {
        if (!string.Equals(binding.ResolverType, ResolverType, StringComparison.Ordinal))
            throw new InvalidOperationException("The secret binding selects a different resolver type.");
        if (string.IsNullOrWhiteSpace(binding.Reference))

View on GitHub (pinned to fe9217bdfa)