{"record":{"id":"ecceda7c6241672b","repo":"elsa-workflows/elsa-core","slug":"a-entitytype-already-exists-with-keyname-key-in-tenant","errorCode":null,"errorMessage":"A {entityType} already exists with {keyName} '{key}' in tenant '{tenantId}'.","messagePattern":"A (.+?) already exists with (.+?) '(.+?)' in tenant '(.+?)'\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Identity/Services/MemoryIdentityUniqueness.cs","lineNumber":31,"sourceCode":"    /// Throws when another Id in the same tenant already owns <paramref name=\"keySelector\"/>.\n    /// Same-Id upserts are allowed so a row can rename itself.\n    /// </summary>\n    public static void EnsureAvailable<T>(\n        MemoryStore<T> store,\n        T entity,\n        Func<T, string?> keySelector,\n        string keyName)\n        where T : Entity\n    {\n        var key = keySelector(entity);\n        var existing = store.Find(candidate =>\n            candidate.TenantId == entity.TenantId\n            && candidate.Id != entity.Id\n            && keySelector(candidate) == key);\n\n        if (existing is not null)\n        {\n            throw new InvalidOperationException(\n                $\"A {typeof(T).Name.ToLowerInvariant()} already exists with {keyName} '{key}' in tenant '{entity.TenantId}'.\");\n        }\n    }\n}\n","sourceCodeStart":13,"sourceCodeEnd":36,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Identity/Services/MemoryIdentityUniqueness.cs#L13-L36","documentation":"MemoryIdentityUniqueness.EnsureAvailable checks an in-memory entity set for another entity of the same type in the same tenant with an equal key (by keySelector) but a different Id. If such a candidate exists it throws InvalidOperationException, since creating/updating the entity would violate the uniqueness constraint (e.g. a duplicate user name or application name within a tenant).","triggerScenarios":"Calling identity APIs that create or rename users/applications/roles via the in-memory identity store when the requested key (e.g. user name) already exists on a different entity within the same tenant. The generic message interpolates the entity type name, key name, key value, and tenant ID.","commonSituations":"Seeding identity data twice on application startup without idempotency checks, registering two users with the same name in one tenant, renaming an entity to a name already taken by another entity, or running multiple seeds concurrently against the shared in-memory store in tests.","solutions":["Before creating/renaming, query the store for an entity with the same key in the tenant and reuse or reject it in application code.","Make startup seeding idempotent: look up the entity by key first and update it rather than adding a new one.","If the key is genuinely distinct, verify the tenant ID is correct - the conflict is scoped per tenant, so a wrong tenant can surface an apparent collision.","Use a real persistence provider with a unique index if stronger guarantees than the in-memory store are needed."],"exampleFix":"// before\nawait userManager.CreateAsync(new User { Name = \"admin\", TenantId = tenantId });\n// after\nvar existing = await userManager.FindByNameAsync(\"admin\", tenantId);\nif (existing is null)\n    await userManager.CreateAsync(new User { Name = \"admin\", TenantId = tenantId });","handlingStrategy":"validation","validationCode":"var duplicate = (await userRegistry.ListAsync(tenantId)).Any(u => u.Name == candidateName);\nif (duplicate) throw new InvalidOperationException($\"A user named '{candidateName}' already exists in tenant '{tenantId}'.\");","typeGuard":null,"tryCatchPattern":"try { await EnsureAvailableAndCreateAsync(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already exists with\"))\n{\n    // handle duplicate: reuse existing entity or surface validation message\n}","preventionTips":["Make all identity seeding idempotent (lookup-before-insert).","Use unique, generated names in tests/parallel seeds to avoid shared in-memory store collisions.","Validate name uniqueness in the UI/API layer before invoking identity services."],"tags":["identity","uniqueness","in-memory-store","duplicate"],"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-15T23:17:13.987Z"}