elsa-workflows/elsa-core · error · InvalidOperationException

The configured secret binding is incompatible with the…

Error message

The configured secret binding is incompatible with the required type or scope.

What it means

ResolveAsync validates that the resolved secret is compatible with the binding's required type and scope via IsCompatible. When the stored secret's type or scope does not match what the binding requires, resolution fails rather than returning material usable in the wrong context.

Solutions

  1. Create a new secret with the correct type/scope via StageAsync and publish a matching binding
  2. Correct the secret's Type/Scope metadata so IsCompatible passes
  3. Update the binding to reference a secret of the required type/scope

Example fix

// before
binding.Reference = otherScopeSecret.Reference; // wrong type/scope
// after
var staged = await resolver.StageAsync(new ManagedSecretBindingWriteRequest { ConnectionId = connId, FieldName = "clientSecret" });
binding.Reference = staged.Reference;
Defensive patterns

Strategy: validation

Validate before calling

var state = await resolver.GetStateAsync(binding);
if (state.SecretExists && !state.IsCompatible) throw new InvalidOperationException("Secret type/scope does not match the binding requirement.");

Type guard

bool IsCompatibleBinding(SecretBinding b) => b.ResolverType == "external-authentication" && b.Ownership == SecretBindingOwnership.Managed;

Try / catch

try { return await resolver.ResolveAsync(binding); }
catch (InvalidOperationException ex) when (ex.Message.Contains("incompatible"))
{ throw new ConfigurationException("Secret binding references a secret of the wrong type or scope.", ex); }

Prevention

When it happens

Trigger: Calling ResolveAsync on a binding whose Reference points to a secret created for a different type or scope; e.g. reusing one secret reference across connections or scopes, or a secret whose stored metadata was changed after the binding was created.

Common situations: Manually editing or migrating secret records and altering Type/Scope fields; pointing two bindings at one reference and later changing scope expectations; schema migrations that renamed scope values.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/0dc3e3d457a95286. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.ExternalAuthentication.Secrets/Services/ElsaSecretBindingResolver.cs:73

        var secret = await secretManager.GetAsync(binding.Reference, cancellationToken);
        if (secret is null)
            return new(false, false);

        var configured = secret is { Status: SecretStatus.Active, LatestActiveVersion: not null };
        if (!configured || !IsCompatible(secret, binding))
            return new(configured, false);

        var test = await secretManager.TestAsync(secret.Name, cancellationToken);
        return new(true, test.Succeeded);
    }

    public async ValueTask<ResolvedSecretBinding> ResolveAsync(SecretBinding binding, CancellationToken cancellationToken = default)
    {
        EnsureResolverType(binding);
        var secret = await secretManager.GetAsync(binding.Reference, cancellationToken)
            ?? throw new InvalidOperationException("The configured secret binding could not be resolved.");
        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.");
    }

View on GitHub (pinned to fe9217bdfa)