{"record":{"id":"9f88ff5ee3dca420","repo":"elsa-workflows/elsa-core","slug":"a-secret-named-request-name-already-exists","errorCode":null,"errorMessage":"A secret named '{request.Name}' already exists.","messagePattern":"A secret named '(.+?)' already exists\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Secrets/Services/DefaultSecretManager.cs","lineNumber":10,"sourceCode":"namespace Elsa.Secrets.Services;\n\npublic class DefaultSecretManager(ISecretNameValidator nameValidator, ISecretStoreRegistry storeRegistry, ISecretTypeRegistry typeRegistry, ISecretRepository repository) : ISecretManager\n{\n    public async Task<Secret> CreateAsync(CreateSecretRequest request, CancellationToken cancellationToken = default)\n    {\n        ValidateName(request.Name);\n        var secret = await CreateSecretAsync(request, cancellationToken);\n        if (!await repository.TryAddOrReplaceDeletedAsync(secret, cancellationToken))\n            throw new InvalidOperationException($\"A secret named '{request.Name}' already exists.\");\n\n        return secret;\n    }\n\n    public async Task<Secret?> GetAsync(string name, CancellationToken cancellationToken = default)\n    {\n        var secret = await repository.GetAsync(nameValidator.Normalize(name), cancellationToken);\n        return secret is { Status: SecretStatus.Deleted } ? null : secret;\n    }\n\n    public async Task<IReadOnlyCollection<Secret>> ListAsync(ListSecretsRequest request, CancellationToken cancellationToken = default)\n    {\n        return (await ListPageAsync(request, cancellationToken)).Items;\n    }\n\n    public async Task<ListSecretsResult> ListPageAsync(ListSecretsRequest request, CancellationToken cancellationToken = default)\n    {\n        var secrets = await repository.ListAsync(cancellationToken);","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Secrets/Services/DefaultSecretManager.cs#L1-L28","documentation":"Thrown by DefaultSecretManager.CreateAsync when the repository refuses to add the newly created secret because an active (non-deleted) secret with the same name already exists. CreateAsync is create-only; rotating or updating an existing secret requires the dedicated APIs.","triggerScenarios":"Calling ISecretManager.CreateAsync(new CreateSecretRequest { Name = \"existing-name\", ... }) when a secret with that name (case-insensitive) already exists and TryAddOrReplaceDeletedAsync returns false.","commonSituations":"Re-running secret provisioning after a previous successful run, users submitting a create form for a name that already exists, or automated pipelines without idempotency.","solutions":["Call manager.GetAsync(name) first; if a secret exists, use RotateAsync or UpdateAsync instead of CreateAsync.","Catch InvalidOperationException from CreateAsync and fall back to the update/rotate path.","Generate unique names or include a scope/environment prefix to avoid collisions.","Make provisioning scripts idempotent (create-if-missing)."],"exampleFix":"// before\nawait manager.CreateAsync(new CreateSecretRequest { Name = \"db-password\", Value = v });\n// after\nif (await manager.GetAsync(\"db-password\") is null)\n    await manager.CreateAsync(new CreateSecretRequest { Name = \"db-password\", Value = v });\nelse\n    await manager.RotateAsync(\"db-password\", new RotateSecretRequest { Value = v });","handlingStrategy":"try-catch","validationCode":"if (await manager.GetAsync(request.Name) != null) throw new InvalidOperationException($\"Secret '{request.Name}' exists; use rotate/update.\");","typeGuard":null,"tryCatchPattern":"try { await manager.CreateAsync(request); }\ncatch (InvalidOperationException e) when (e.Message.Contains(\"already exists\")) { await manager.RotateAsync(request.Name, rotateFrom(request)); }","preventionTips":["Implement create-or-rotate logic instead of blind create.","Expose clear UI/API errors when a name is taken before submit.","Use unique names per environment/scope."],"tags":["secrets","duplicate","conflict","api"],"backgroundTag":"file-already-exists","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}