elsa-workflows/elsa-core · error · InvalidOperationException

Secret ' ' has no active version.

Error message

Secret '{secret.Name}' has no active version.

What it means

GetLatestActiveVersion throws InvalidOperationException when the secret is Active but has no LatestActiveVersion. The secret entity exists and is active, yet none of its versions is currently active, so there is no payload to resolve. This indicates corrupted or transitional version state.

Solutions

  1. Create or promote a new active version for the secret (rotate the secret).
  2. Fix the rotation flow so a new active version is promoted before revoking the old one.
  3. Restore the missing version record from backup/migration if data was lost.
  4. Check version expiry windows so at least one version remains active.

Example fix

// before
await secretManager.RotateAsync("DbPassword"); // rotation revokes before promoting
// after
await secretManager.RotateAsync("DbPassword", options => options.PromoteNewVersionBeforeRevokingOld = true); // ensure a new active version exists
Defensive patterns

Strategy: validation

Validate before calling

var secret = await secretManager.GetAsync(name, ct);
if (secret?.LatestActiveVersion is null)
    throw new InvalidOperationException($"Secret '{name}' has no active version; rotate it first.");

Type guard

bool HasActiveVersion(Secret? s) => s?.LatestActiveVersion is not null;

Try / catch

try { var value = await resolver.ResolveAsync(reference, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("has no active version")) { logger.LogError(ex, "Rotating secret {Name}", reference.Name); await manager.RotateAsync(reference.Name, ct); }

Prevention

When it happens

Trigger: Resolving a secret whose LatestActiveVersion is null — e.g. all versions expired/revoked, a rotation left no active version, or the secret was created without an initial active version.

Common situations: Rotation job revoked the old version before promoting the new one; manual version deletion removed the only active version; clock/timezone issues making all versions expired; import/migration that skipped version records.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.Secrets/Services/DefaultSecretManager.cs:207

        var version = new SecretVersion { Version = 1, ExpiresAt = request.ExpiresAt };
        version.Payload = await store.WriteAsync(secret, version, CreatePayload(request), cancellationToken);
        secret.Versions.Add(version);

        return secret;
    }

    private async Task<Secret> GetExistingAsync(string name, CancellationToken cancellationToken)
    {
        var secret = await GetAsync(name, cancellationToken);
        return secret == null ? throw new KeyNotFoundException($"Secret '{name}' was not found.") : secret;
    }

    private static SecretVersion GetLatestActiveVersion(Secret secret)
    {
        if (secret.Status != SecretStatus.Active)
            throw new InvalidOperationException($"Secret '{secret.Name}' is not active.");

        return secret.LatestActiveVersion ?? throw new InvalidOperationException($"Secret '{secret.Name}' has no active version.");
    }

    private void ValidateName(string name)
    {
        if (!nameValidator.IsValid(name, out var error))
            throw new InvalidOperationException(error);
    }

    private static void EnsureCanWrite(ISecretStore store)
    {
        if (!store.Descriptor.Capabilities.HasFlag(SecretStoreCapabilities.Write))
            throw new InvalidOperationException($"Secret store '{store.Name}' does not support writing secrets.");
    }

    private static IEnumerable<Secret> ApplyFilters(IEnumerable<Secret> secrets, ListSecretsRequest request)
    {
        var query = secrets.Where(x => x.Status != SecretStatus.Deleted);

View on GitHub (pinned to fe9217bdfa)