elsa-workflows/elsa-core · error · InvalidOperationException
Secret ' ' is not compatible with required scope ' '.
Error message
Secret '{reference.Name}' is not compatible with required scope '{reference.Scope}'. What it means
ResolveAsync optionally validates that the secret's Scope matches the SecretReference.Scope (case-insensitive) and throws InvalidOperationException on mismatch. This enforces that secrets are only consumed within their intended scope (environment/tenant/module). Fires only when the reference specifies a Scope.
Solutions
- Align the reference Scope with the secret's actual Scope.
- Update the secret's Scope to the expected value if appropriate.
- Create a correctly scoped secret for the target environment/tenant.
- Remove Scope from the reference if cross-scope access is intended.
Example fix
// before
var value = await resolver.ResolveAsync(new SecretReference("SftpPassword", scope: "Production"));
// after
var value = await resolver.ResolveAsync(new SecretReference("SftpPassword", scope: "Staging")); // matches secret.Scope Defensive patterns
Strategy: validation
Validate before calling
var secret = await secretManager.GetAsync(reference.Name, ct);
if (secret is not null && !string.IsNullOrEmpty(reference.Scope) &&
!string.Equals(secret.Scope, reference.Scope, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException($"Scope mismatch for secret '{reference.Name}'."); Type guard
bool ScopeMatches(Secret? s, string? expected) =>
string.IsNullOrEmpty(expected) || string.Equals(s?.Scope, expected, StringComparison.OrdinalIgnoreCase); Try / catch
try { var value = await resolver.ResolveAsync(reference, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not compatible with required scope")) { logger.LogError("Secret {Name} scope mismatch: {Msg}", reference.Name, ex.Message); throw; } Prevention
- Standardize scope labels across environments
- Set Scope consistently at secret creation
- Verify scope after environment promotion
When it happens
Trigger: Resolving a SecretReference with Scope set while the stored secret's Scope differs (or is null), e.g. reference scoped to 'Production' but secret scoped to 'Staging'.
Common situations: Promoting configuration between environments where scope labels differ; multi-tenant setups with per-tenant scoped secrets; scope renamed during refactoring.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- A configuration key is required.
- A value is required for encrypted secrets.
- Configuration connection
- {error}
- Secret expression reference must specify a secret name.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/83f489dfaa44fbe1.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Secrets/Services/DefaultSecretResolver.cs:17
namespace Elsa.Secrets.Services;
public class DefaultSecretResolver(ISecretManager secretManager) : ISecretResolver
{
public Task<string> ResolveAsync(string name, CancellationToken cancellationToken = default) => ResolveAsync(new SecretReference(name), cancellationToken);
public async Task<string> ResolveAsync(SecretReference reference, CancellationToken cancellationToken = default)
{
var secret = await secretManager.GetAsync(reference.Name, cancellationToken);
if (secret == null)
throw new InvalidOperationException($"Secret '{reference.Name}' was not found.");
if (!string.IsNullOrWhiteSpace(reference.TypeName) && !string.Equals(secret.TypeName, reference.TypeName, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException($"Secret '{reference.Name}' is not compatible with required type '{reference.TypeName}'.");
if (!string.IsNullOrWhiteSpace(reference.Scope) && !string.Equals(secret.Scope, reference.Scope, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException($"Secret '{reference.Name}' is not compatible with required scope '{reference.Scope}'.");
var payload = await secretManager.ResolvePayloadAsync(secret, cancellationToken);
return payload.Value!;
}
}
View on GitHub (pinned to fe9217bdfa)