elsa-workflows/elsa-core · error · InvalidOperationException
The secret binding reference is required.
Error message
The secret binding reference is required.
What it means
After confirming the resolver type matches, EnsureResolverType requires the SecretBinding to carry a non-empty Reference pointing at the stored secret. A binding with a null, empty, or whitespace Reference cannot identify which secret to resolve, so the resolver throws this InvalidOperationException. It is a required-field guard for the binding's secret pointer.
Solutions
- Set binding.Reference to the identifier of the stored secret (or re-stage the value with the managed writer, which assigns it)
- If the binding came from imported config, fix the export/import mapping so the reference field survives serialization
- If using a custom ISecretWriter, ensure StageAsync always populates SecretBinding.Reference with the staged secret's reference
- Delete bindings that can never be resolved instead of keeping empty shells in connection.SecretBindings
Example fix
// before
var binding = new SecretBinding { ResolverType = resolverType }; // Reference missing
// after
var binding = await writer.StageAsync(new(connectionId, field, value), ct); // Reference assigned by writer Defensive patterns
Strategy: validation
Validate before calling
// before resolving
if (string.IsNullOrWhiteSpace(binding.Reference))
throw new InvalidOperationException("Secret binding is missing its Reference; re-stage the secret value."); Type guard
bool HasReference(SecretBinding b) => !string.IsNullOrWhiteSpace(b.Reference);
Try / catch
try { var value = await resolver.ResolveAsync(binding, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("reference is required"))
{ logger.LogError("Binding for field has no Reference; re-create it via the managed writer."); } Prevention
- Round-trip test connection import/export to ensure the reference field is preserved
- Assert in custom ISecretWriter implementations that StageAsync sets Reference
- Reject bindings with empty references at configuration load time
- Treat bindings as opaque values created only by the managed writer
When it happens
Trigger: Calling GetStateAsync, ResolveAsync, or RemoveAsync with a SecretBinding whose Reference property is null/empty/whitespace — e.g. a binding constructed manually without a reference, or a writer that returned a staged binding before assigning its reference.
Common situations: Deserializing connections from JSON where the reference field was omitted or named differently; custom ISecretWriter implementations that forget to set Reference on the staged binding; importing/exporting connection definitions across environments with truncated binding data.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- The configured secret binding could not be resolved.
- The secret binding selects a different resolver type.
- 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/ba28091af09e3681.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.ExternalAuthentication.Secrets/Services/ElsaSecretBindingResolver.cs:90
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))
throw new InvalidOperationException("The secret binding reference is required.");
}
private static bool IsCompatible(Secret secret, SecretBinding binding) =>
(string.IsNullOrWhiteSpace(binding.ExpectedType) || string.Equals(secret.TypeName, binding.ExpectedType, StringComparison.OrdinalIgnoreCase)) &&
(string.IsNullOrWhiteSpace(binding.ExpectedScope) || string.Equals(secret.Scope, binding.ExpectedScope, StringComparison.OrdinalIgnoreCase));
}
View on GitHub (pinned to fe9217bdfa)