elsa-workflows/elsa-core · error · InvalidOperationException
A required secret binding resolver is unavailable.
Error message
A required secret binding resolver is unavailable.
What it means
Thrown by GetSecretFingerprintAsync (reached via RefreshAsync) when no ISecretBindingResolver capable of resolving the connection's secret binding is registered in the service provider. It indicates a misconfigured external-authentication installation: the secret binding's resolver type was never registered or the binding references an unknown resolver.
Solutions
- Register the ISecretBindingResolver implementation referenced by the connection's secret binding in DI before issuing or refreshing tokens.
- Inspect the connection's secret binding and correct its ResolverType so it matches a registered resolver.
- Verify the Elsa.ExternalAuthentication feature setup registered all built-in secret binding resolvers.
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at src/modules/Elsa.ExternalAuthentication/Services/DefaultExternalAuthenticationTokenIssuer.cs:100 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/99c6c3c2d4626c9f.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.ExternalAuthentication/Services/DefaultExternalAuthenticationTokenIssuer.cs:100
return new(
accessToken.Token,
"Bearer",
Math.Max(0, (long)(accessToken.ExpiresAt - now).TotalSeconds),
refreshToken,
Math.Max(0, (long)(session.RefreshExpiresAt - now).TotalSeconds),
Math.Max(0, (long)(session.ExpiresAt - now).TotalSeconds));
}
private static string CreateRefreshToken(string sessionId) => $"{sessionId}.{Convert.ToBase64String(RandomNumberGenerator.GetBytes(32)).TrimEnd('=').Replace('+', '-').Replace('/', '_')}";
private static string Hash(string token) => Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(token)));
private async ValueTask<string> GetSecretFingerprintAsync(IDictionary<string, SecretBinding> bindings, CancellationToken cancellationToken)
{
var fingerprints = new List<string>();
foreach (var (name, binding) in bindings)
{
var resolver = secretBindingResolvers.FirstOrDefault(x => string.Equals(x.Type, binding.ResolverType, StringComparison.Ordinal))
?? throw new InvalidOperationException("A required secret binding resolver is unavailable.");
var resolved = await resolver.ResolveAsync(binding, cancellationToken);
fingerprints.Add($"{name}:{resolved.GenerationFingerprint}");
resolved.Value.Dispose();
}
return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", fingerprints.OrderBy(x => x, StringComparer.Ordinal)))));
}
}
View on GitHub (pinned to fe9217bdfa)