elsa-workflows/elsa-core · error · InvalidOperationException
{error}
Error message
{error} What it means
This error's message is dynamic: it is whatever error string the secret type provider's ValidateRotation method produced when it rejected the rotation request. RotateAsync calls provider.ValidateRotation and, on failure, throws InvalidOperationException with the provider-supplied message.
Solutions
- Read the thrown message - it names the exact validation failure - and correct the RotateSecretRequest accordingly.
- Consult the secret type provider's rotation requirements (descriptor/documentation) and supply all required fields.
- Test the request against provider.ValidateRotation in a pre-check before calling RotateAsync.
- Catch InvalidOperationException around RotateAsync to surface the provider error to the user.
Example fix
// before
await manager.RotateAsync("api-key", new RotateSecretRequest { Value = "" }); // provider rejects empty value
// after
var request = new RotateSecretRequest { Value = newKey };
if (!provider.ValidateRotation(request, storeName, out var error))
throw new InvalidOperationException("Fix rotation request: " + error);
await manager.RotateAsync("api-key", request); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check using the same provider used by the manager if (!typeRegistry.Get(secret.TypeName).ValidateRotation(request, secret.StoreName, out var error)) throw new InvalidOperationException(error);
Try / catch
try { await manager.RotateAsync(name, request); }
catch (InvalidOperationException e) { /* surface e.Message - it is the provider's validation error */ } Prevention
- Read the provider error message; it names the exact failing rule.
- Keep rotation requests type-specific; do not reuse bodies across secret types.
- Add contract tests for each secret type's rotation requirements.
When it happens
Trigger: Calling ISecretManager.RotateAsync with a RotateSecretRequest that fails the specific secret type provider's validation rules - e.g. missing required fields, invalid value format for that secret type, or disallowed rotation parameters.
Common situations: Rotating a custom secret type whose rotation requirements (e.g. new value length/format, required metadata) are not met; API clients sending the same body used for a different secret type.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- The secret field name must contain a letter or digit.
- The configured secret binding is not active.
- Configuration connection
- The configured secret binding is invalid.
- 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/2dee7bb1c3a07bc6.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Secrets/Services/DefaultSecretManager.cs:70
var secret = await GetExistingAsync(name, cancellationToken);
secret.DisplayName = string.IsNullOrWhiteSpace(request.DisplayName) ? secret.Name : request.DisplayName.Trim();
secret.Description = string.IsNullOrWhiteSpace(request.Description) ? null : request.Description.Trim();
secret.UpdatedAt = DateTimeOffset.UtcNow;
await repository.SaveAsync(secret, cancellationToken);
return secret;
}
public async Task<Secret> RotateAsync(string name, RotateSecretRequest request, CancellationToken cancellationToken = default)
{
var secret = await GetExistingAsync(name, cancellationToken);
if (secret.Status == SecretStatus.Revoked)
throw new InvalidOperationException($"Secret '{secret.Name}' is revoked and cannot be rotated.");
var provider = typeRegistry.Get(secret.TypeName);
if (!provider.ValidateRotation(request, secret.StoreName, out var error))
throw new InvalidOperationException(error);
var store = storeRegistry.Get(secret.StoreName);
EnsureCanWrite(store);
var nextVersion = secret.Versions.Count == 0 ? 1 : secret.Versions.Max(x => x.Version) + 1;
var version = new SecretVersion { Version = nextVersion, ExpiresAt = request.ExpiresAt };
version.Payload = await store.WriteAsync(secret, version, CreatePayload(request), cancellationToken);
foreach (var activeVersion in secret.Versions.Where(x => x.Status == SecretStatus.Active))
activeVersion.Status = SecretStatus.Retired;
secret.Versions.Add(version);
secret.Status = SecretStatus.Active;
secret.UpdatedAt = DateTimeOffset.UtcNow;
await repository.SaveAsync(secret, cancellationToken);
return secret;
}
View on GitHub (pinned to fe9217bdfa)