Vault Error: 'alias already exists' — Identity Entity Alias Conflict on Login
Fix Vault's identity 'alias already exists' error: understand mount_accessor keying, list and repoint entity aliases, merge duplicate entities, and repair templated policies broken by a remounted auth method.
- #vault
- #secrets
- #security-hardening
- #troubleshooting
- #errors
Stuck on this HashiCorp Vault error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
$ vault write identity/entity-alias name="svc-payments" \
canonical_id="8d4a1f2c-6b3e-4a91-9f77-2c1e5a0b7d33" \
mount_accessor="auth_approle_1f2e3d4c"
Error making API request.
URL: PUT https://vault.example.com:8200/v1/identity/entity-alias
Code: 400. Errors:
* alias already exists: an alias with the name "svc-payments" and mount accessor
"auth_approle_1f2e3d4c" is already mapped to a different entity
You may instead hit it indirectly during a login or an entity create:
Error making API request.
URL: PUT https://vault.example.com:8200/v1/identity/entity
Code: 400. Errors:
* entity name is already in use
* alias "jdoe" is already tied to a different entity
What It Means
Vault’s identity system sits above the auth methods. Each human or workload is an entity with a UUID (identity.entity.id), and each way that entity can log in is an alias. An alias is keyed by the pair (mount_accessor, name) — the accessor of the auth mount plus the login name that mount reports. Vault enforces that this pair is globally unique: one alias name per auth mount can map to exactly one entity. When something tries to attach an already-claimed (mount_accessor, name) pair to a second entity, you get alias already exists.
That constraint exists because aliases are how Vault decides which entity a token belongs to. If userpass/jdoe could map to two entities, a login could not deterministically resolve identity, and entity-scoped policies, group membership, and identity-templated paths would become ambiguous. In practice the error almost always means one of two things: someone is trying to give a second entity a login that the first entity already owns, or you have accidentally created duplicate entities for the same real principal — commonly because the same person logs in through two different auth mounts (LDAP and OIDC), each of which correctly creates its own alias, and someone then tries to unify them by hand instead of merging the entities.
Common Causes
- A configuration-as-code run recreates entity aliases on every apply, colliding with the alias Vault auto-created at first login.
- The same human authenticates through two auth mounts (e.g.
ldap/andoidc/), producing two entities that a later script tries to collapse incorrectly. - An auth method was disabled and re-enabled, which mints a new mount accessor, orphaning every alias tied to the old one.
- Two entities were created with overlapping aliases before Vault’s uniqueness check was hit, and now neither can be updated.
- An external identity provider changed the claim used as the alias name (e.g.
emailtosub), so logins create fresh aliases alongside stale ones. - Automation writes
identity/entitywith analiasesblock instead of usingidentity/entity-alias, unintentionally reassigning ownership.
Diagnostic Commands
Start by enumerating entities so you can see whether duplicates exist:
vault list identity/entity/id
vault list -format=json identity/entity/name | jq -r '.[]'
Look up the entity that currently owns the contested alias. Reading by name is usually easier than by UUID:
vault read -format=json identity/entity/name/svc-payments | jq '{id: .data.id, aliases: [.data.aliases[] | {id, name, mount_accessor, mount_path}]}'
Inspect a specific alias directly to see its canonical_id — the entity it points at:
vault read -format=json identity/entity-alias/id/2b6f9c81-4e0d-4c7a-b3d2-9a11e7f45c60 \
| jq '{name: .data.name, canonical_id: .data.canonical_id, mount_accessor: .data.mount_accessor}'
Now confirm the mount accessors in play. This is the step people skip, and it is the one that explains most “but the alias looks identical” confusion:
vault auth list -detailed
The output shows each auth mount’s Accessor column, e.g. auth_approle_1f2e3d4c. If the accessor in your alias definition does not appear here, the mount was deleted and recreated and every alias tied to that accessor is now dead weight.
Finally, check what groups the entity belongs to, since group membership is often the real reason a login “lost” its permissions:
vault list identity/group/id
vault read -format=json identity/group/name/platform-admins | jq '.data | {member_entity_ids, type, alias}'
Internal groups take explicit member_entity_ids; external groups derive membership from a group alias matching a claim or LDAP group from the identity provider. A merged or replaced entity silently drops out of an internal group unless you update it.
Step-by-Step Resolution
- Identify both entities involved. Given the alias name and the mount accessor, find the current owner and the entity you wanted it on:
CONTESTED="svc-payments"
vault read -format=json identity/entity/name/$CONTESTED | jq '.data.id'
- If the two entities represent the same principal, merge them rather than reassigning aliases one at a time. Merging moves all aliases and group memberships from the source entities into the target, then deletes the sources:
vault write identity/entity/merge \
from_entity_ids="4c9d2a1b-7e3f-4d88-a2c1-5b6e0f9a3d47" \
to_entity_id="8d4a1f2c-6b3e-4a91-9f77-2c1e5a0b7d33"
- If they are genuinely different principals and the alias is on the wrong one, repoint the alias by writing a new
canonical_idonto the existing alias ID. This is an update, not a create, so it does not trip the uniqueness check:
vault write identity/entity-alias/id/2b6f9c81-4e0d-4c7a-b3d2-9a11e7f45c60 \
canonical_id="8d4a1f2c-6b3e-4a91-9f77-2c1e5a0b7d33" \
name="svc-payments" \
mount_accessor="auth_approle_1f2e3d4c"
- If an auth method was re-enabled, capture the new accessor and rebuild the aliases against it. Old aliases pointing at the dead accessor should be deleted:
NEW_ACCESSOR=$(vault auth list -format=json | jq -r '."approle/".accessor')
vault write identity/entity-alias name="svc-payments" \
canonical_id="8d4a1f2c-6b3e-4a91-9f77-2c1e5a0b7d33" \
mount_accessor="$NEW_ACCESSOR"
- Make your automation idempotent so it stops recreating the conflict. Look up first, create only if absent:
ALIAS_ID=$(vault list -format=json identity/entity-alias/id 2>/dev/null \
| jq -r '.[]' \
| while read -r id; do
vault read -format=json "identity/entity-alias/id/$id" \
| jq -r --arg n "svc-payments" --arg a "$NEW_ACCESSOR" \
'select(.data.name==$n and .data.mount_accessor==$a) | .data.id'
done)
if [ -z "$ALIAS_ID" ]; then
vault write identity/entity-alias name="svc-payments" \
canonical_id="$ENTITY_ID" mount_accessor="$NEW_ACCESSOR"
else
vault write "identity/entity-alias/id/$ALIAS_ID" canonical_id="$ENTITY_ID"
fi
- Re-verify any templated policies that depend on identity. These break the moment an entity ID changes, because the rendered path changes with it:
path "secret/data/{{identity.entity.id}}/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "secret/data/teams/{{identity.entity.aliases.auth_approle_1f2e3d4c.name}}/*" {
capabilities = ["read", "list"]
}
After a merge, the surviving entity has a different ID than one of the originals, so any data written under the old {{identity.entity.id}} path is no longer reachable by that policy. Copy the data to the new path or key your templates on a stable alias name instead. If the resulting access failure looks like a plain permission denial rather than an identity issue, cross-check against Vault error: rate limit quota exceeded to rule out quota rejections, which surface with a different status code.
Prevention
- Key templated policies on a stable value such as an alias name or a group, not on
identity.entity.id, when entities may be merged. - Treat mount accessors as immutable inputs: never disable and re-enable an auth method in place without planning the alias rebuild.
- Make identity automation read-then-write (idempotent) rather than create-only, so reruns update instead of colliding.
- Standardise on one alias-name claim per identity provider and pin it in the auth method config so it cannot drift.
- Prefer external groups bound to IdP groups over hand-maintained
member_entity_idslists, which decay after merges. - Audit for duplicate entities periodically by listing entities and flagging any two with aliases for the same human.
Related Errors
permission deniedafter a merge — the templated policy path changed with the entity ID; re-check the rendered path.entity not found/invalid canonical_id— the target entity was deleted while an alias still referenced it.namespace not found— identity objects live per namespace; you are querying the wrong one. See Vault error: namespace not found.failed to validate credentials— an auth-method-level failure that happens before identity resolution ever runs.
Frequently Asked Questions
Why does the same person end up with two entities? Because each auth mount creates its own alias, and Vault has no way to know that ldap/jdoe and oidc/jdoe@example.com are the same human. That is expected — the fix is to attach both aliases to one entity, or merge the two entities with identity/entity/merge.
Is merging entities reversible? No. The source entities are deleted and their aliases and group memberships move to the target. Capture vault read -format=json identity/entity/id/<id> for every entity involved before merging so you can rebuild if the result is wrong.
Why did all my aliases break after I re-enabled an auth method? Disabling an auth method destroys its mount accessor; re-enabling mints a new one. Since aliases are keyed on (mount_accessor, name), every alias tied to the old accessor is orphaned. Run vault auth list -detailed to get the new accessor and recreate them.
Do entity aliases replicate across clusters? Identity data replicates on performance replication (Vault Enterprise), but tokens and leases issued on a performance secondary stay local, so entity IDs are consistent while sessions are not. For more identity and auth fixes, see the Vault guides.
Fixed it? Get 500 HashiCorp Vault & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.