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
- Re-stage the secret material via StageAsync and republish a fresh binding
- Delete/recreate the binding so it points to an existing secret
- 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
- Migrate secret store data along with bindings when restoring backups
- Never delete secrets that live bindings still reference; use CAS publish/remove to keep them consistent
- Validate bindings at startup so broken references fail fast with a clear message
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
- The secret binding selects a different resolver type.
- The secret binding reference is required.
- Configuration connection
- The configured secret binding could not be resolved.
- The configured secret binding is invalid.
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)