elsa-workflows/elsa-core · error · InvalidOperationException
Secret expression reference must specify a secret name.
Error message
Secret expression reference must specify a secret name.
What it means
After confirming the expression value is a SecretReference, the handler validates that the reference names a secret. A SecretReference with an empty, null, or whitespace Name cannot be resolved and triggers this InvalidOperationException. It prevents a silent null/empty resolution of a misconfigured secret reference.
Solutions
- Set the Name on the SecretReference: new SecretReference { Name = "my-secret" }.
- Check the workflow definition JSON/activity config for an empty secret-name field and fill it in.
- If the name is sourced from configuration, verify the config value is non-empty before deploying.
- Add a validation step when building activities programmatically to reject SecretReferences without a Name.
Example fix
// before
var reference = new SecretReference(); // Name not set
var expr = new Expression("Secret", reference);
// after
var reference = new SecretReference { Name = configuration["Secrets:ApiKey"]! };
if (string.IsNullOrWhiteSpace(reference.Name)) throw new ArgumentException("Secret name must be configured.");
var expr = new Expression("Secret", reference); Defensive patterns
Strategy: validation
Validate before calling
if (expression.Value is SecretReference r && string.IsNullOrWhiteSpace(r.Name)) throw new InvalidOperationException("SecretReference.Name must be a non-empty string before evaluation."); Try / catch
try { return await handler.EvaluateAsync(expression, returnType, context, options); }
catch (InvalidOperationException ex) when (ex.Message.Contains("secret name")) { /* report misconfigured secret reference */ } Prevention
- Validate secret references at workflow-publish time, not just runtime.
- Make secret-name fields required in custom designers.
- Never construct SecretReference without a Name; add an invariant check in helpers.
When it happens
Trigger: Creating a SecretReference without setting Name (new SecretReference() or default), or building one from a variable/config value that is empty or whitespace at design time.
Common situations: A designer/property binding left the secret name blank; the secret name came from an empty app setting or environment variable used at workflow authoring time; copy-pasted activity configuration dropped the Name field.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- The secret field name must contain a letter or digit.
- Configuration connection
- The configured secret binding is invalid.
- Secret expression value must be a SecretReference.
- {error}
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/b02c3bc43e2ba47e.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Secrets/Expressions/SecretExpressionHandler.cs:19
using Elsa.Expressions.Contracts;
using Elsa.Expressions.Helpers;
using Elsa.Expressions.Models;
namespace Elsa.Secrets.Expressions;
/// <summary>
/// Resolves Secret expressions through the configured secret resolver.
/// </summary>
public class SecretExpressionHandler(ISecretResolver secretResolver, IWellKnownTypeRegistry wellKnownTypeRegistry) : IExpressionHandler
{
/// <inheritdoc />
public async ValueTask<object?> EvaluateAsync(Expression expression, Type returnType, ExpressionExecutionContext context, ExpressionEvaluatorOptions options)
{
if (expression.Value is not SecretReference reference)
throw new InvalidOperationException("Secret expression value must be a SecretReference.");
if (string.IsNullOrWhiteSpace(reference.Name))
throw new InvalidOperationException("Secret expression reference must specify a secret name.");
var value = await secretResolver.ResolveAsync(reference, context.CancellationToken);
return value.ConvertTo(returnType, new ObjectConverterOptions(WellKnownTypeRegistry: wellKnownTypeRegistry));
}
}
View on GitHub (pinned to fe9217bdfa)