{"record":{"id":"1271fad2682ce010","repo":"elsa-workflows/elsa-core","slug":"secret-expression-value-must-be-a-secretreference","errorCode":null,"errorMessage":"Secret expression value must be a SecretReference.","messagePattern":"Secret expression value must be a SecretReference\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Secrets/Expressions/SecretExpressionHandler.cs","lineNumber":16,"sourceCode":"using Elsa.Expressions.Contracts;\nusing Elsa.Expressions.Helpers;\nusing Elsa.Expressions.Models;\n\nnamespace Elsa.Secrets.Expressions;\n\n/// <summary>\n/// Resolves Secret expressions through the configured secret resolver.\n/// </summary>\npublic class SecretExpressionHandler(ISecretResolver secretResolver, IWellKnownTypeRegistry wellKnownTypeRegistry) : IExpressionHandler\n{\n    /// <inheritdoc />\n    public async ValueTask<object?> EvaluateAsync(Expression expression, Type returnType, ExpressionExecutionContext context, ExpressionEvaluatorOptions options)\n    {\n        if (expression.Value is not SecretReference reference)\n            throw new InvalidOperationException(\"Secret expression value must be a SecretReference.\");\n\n        if (string.IsNullOrWhiteSpace(reference.Name))\n            throw new InvalidOperationException(\"Secret expression reference must specify a secret name.\");\n\n        var value = await secretResolver.ResolveAsync(reference, context.CancellationToken);\n        return value.ConvertTo(returnType, new ObjectConverterOptions(WellKnownTypeRegistry: wellKnownTypeRegistry));\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":25,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Secrets/Expressions/SecretExpressionHandler.cs#L1-L25","documentation":"SecretExpressionHandler evaluates a 'Secret' expression by expecting Expression.Value to be a SecretReference. If the expression was built with some other value type (a string, raw object, etc.), it throws this InvalidOperationException immediately. The expression payload, not the runtime input, is what is validated.","triggerScenarios":"Constructing an Expression for the secret expression type with Value set to something other than a SecretReference (e.g. a plain string secret name or a deserialized/round-tripped expression that lost its typed value).","commonSituations":"Hand-building expressions in code instead of using the Secret expression factory; persisting workflow definitions that round-trip expression values as JSON losing the typed SecretReference; copying expression snippets from older workflow formats.","solutions":["Wrap the secret name in a SecretReference when building the expression: new Expression(...){ Value = new SecretReference { Name = \"my-secret\" } }.","Use the provided secret expression factory/helper rather than constructing Expression objects manually.","Check how the workflow definition was serialized; ensure the expression value round-trips as a SecretReference.","Verify the activity or designer producing the expression emits the correct expression type/value pair."],"exampleFix":"// before\nvar expr = new Expression(\"Secret\", \"my-secret\");\n\n// after\nvar expr = new Expression(\"Secret\", new SecretReference { Name = \"my-secret\" });","handlingStrategy":"type-guard","validationCode":"if (expression.Value is not SecretReference) throw new InvalidOperationException(\"Secret expression requires a SecretReference value.\");","typeGuard":"static bool IsSecretExpression(Expression e) => e.Value is SecretReference { Name: not null and not \"\" };","tryCatchPattern":"try { var value = await handler.EvaluateAsync(expression, returnType, context, options); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"SecretReference\")) { /* fix expression construction or surface config error */ }","preventionTips":["Always create secret expressions via the dedicated factory methods.","Unit-test expression serialization round-trips in custom activities.","Never put raw strings in Secret-typed expressions."],"tags":["expressions","secrets","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}