elsa-workflows/elsa-core · error · InvalidOperationException
A secret named ' ' already exists.
Error message
A secret named '{secret.Name}' already exists. What it means
VNextSecretRepository.AddAsync saves a new secret with expectedVersion 0, so the underlying document store rejects the write if a document with the same name index already exists (DocumentStoreConcurrencyException). The repository translates that into this InvalidOperationException. It functions as a duplicate-name guard for secret creation.
Solutions
- Check existence first (e.g. query the repository by name) or use an upsert-style API instead of AddAsync before creating the secret.
- Catch InvalidOperationException (or the underlying DocumentStoreConcurrencyException) around AddAsync and treat it as 'already created'.
- Rename the new secret if a distinct secret was intended; names are unique per tenant.
- Serialize creation through a single worker/job if concurrent seeding is the cause.
Example fix
// before
await secretRepository.AddAsync(new Secret { Name = "api-key", ... }, ct);
// after
var existing = await secretRepository.FindAsync(s => s.Name == "api-key", ct);
if (existing is null)
await secretRepository.AddAsync(new Secret { Name = "api-key", ... }, ct); Defensive patterns
Strategy: try-catch
Validate before calling
var existing = await secretRepository.FindAsync(s => s.Name == secret.Name, cancellationToken);
if (existing is not null) throw new InvalidOperationException($"Secret '{secret.Name}' already exists."); Try / catch
try { await secretRepository.AddAsync(secret, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already exists")) { /* handle duplicate: load or skip */ } Prevention
- Always check for an existing secret by name before AddAsync.
- Make secret provisioning idempotent (create-if-missing).
- Use unique names that include environment or tenant scope.
When it happens
Trigger: Calling AddAsync (via ISecretRepository.AddAsync) with a Secret whose Name matches an existing secret in the default tenant; two concurrent AddAsync calls racing to create the same secret name.
Common situations: Workflow setup code or a provisioning script creating secrets on every run without an existence check; retry logic re-running a creation step after a partial failure; two environments/instances racing to seed the same secret.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- A secret named ' ' already exists.
- A secret named ' ' already exists.
- Document ' ' in storage unit ' ' expected version ' ' but…
- Document ' ' in storage unit ' ' expected version ' ' but…
- Document ' ' in storage unit ' ' expected version ' ' but…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/780b4380d4f677f2.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Secrets.Persistence.VNext/Repositories/VNextSecretRepository.cs:81
new DocumentQuery(StorageUnitName, new Dictionary<string, string?> { [nameof(Secret.Status)] = status.ToString() }),
cancellationToken);
results.AddRange(documents.Select(Deserialize));
}
return results.OrderBy(x => x.Name, StringComparer.OrdinalIgnoreCase).ToList();
}
public async Task AddAsync(Secret secret, CancellationToken cancellationToken = default)
{
EnsureDefaultTenant();
try
{
await SaveAsync(secret, expectedVersion: 0, cancellationToken);
}
catch (DocumentStoreConcurrencyException)
{
throw new InvalidOperationException($"A secret named '{secret.Name}' already exists.");
}
}
public async Task<bool> TryAddOrReplaceDeletedAsync(Secret secret, CancellationToken cancellationToken = default)
{
EnsureDefaultTenant();
while (true)
{
var existing = await LoadDocumentAsync(secret.Name, cancellationToken);
if (existing?.Secret.Status is not null and not SecretStatus.Deleted)
return false;
try
{
await SaveAsync(secret, existing?.Document.Version ?? 0, cancellationToken);
return true;
}
catch (DocumentStoreConcurrencyException)View on GitHub (pinned to fe9217bdfa)