goauthentik / goauthentik/authentik
Upgrade from v2026.2.2 to v2026.5.x: duplicate key value violates unique constraint `authentik_stages_consent_user_id_application_id_p_<uuid>_uniq`
- Dominant language
- Python
- Stars
- 25.6k
- Forks
- 2k
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 659
Description
### Describe the bug
Upgraded from v2026.2.2 to v2026.5.x.
Logging into applications like ArgoCD and OpenWebUI.
Getting a `duplicate key value violates unique constraint authentik_stages_consent_user_id_application_id_p__uniq` on login to _authentik_ during the login flow.
Going to the user accounts affected and deleting all tokens fixes the issue:
`Directory -> Users -> -> Credentials/Tokens -> Explicit Consent -> `
### How to reproduce
1. `argocd version 3.4.5`
2. configure argocd via the [official docs here](https://integrations.goauthentik.io/infrastructure/argocd/)
3. configure all login flows for all apps to use MFA (e.g.: chrome signin key, ios key, yubikey, etc)
4. login with created workflow - should create token w/ explicit consent scopes
5. token expires at some point
6. try to log in again
7. hit error
As I said above - going to the user accounts affected and deleting all tokens fixes the issue:
`Directory -> Users -> -> Credentials/Tokens -> Explicit Consent -> `
### Expected behavior
Not sure. The old token should probably be ignored? 2026.2.2 used to work with all of my expired tokens fine.
### Screenshots
_If it happens again I will update this issue._
### Additional context
I originally _thought_ that this issue was related. https://github.com/goauthentik/authentik/issues/22661#issuecomment-5091673441
### Deployment Method
Kubernetes
### Version
2026.5.4
### Relevant log output
```shell
duplicate key value violates unique constraint "authentik_stages_consent_user_id_application_id_p_e44c6458_uniq"
duplicate key value violates unique constraint "authentik_stages_consent_user_id_application_id_p_e44c6458_uniq" DETAIL: Key (user_id, application_id, permissions)=(6, a6a4972a-ecd3-4add-98d9-542c96b068a7, email openid profile) already exists.
Traceback (most recent call last):
File "/authentik/flows/views/executor.py", line 348, in post
stage_response = self.current_stage_view.dispatch(request)
File "/ak-root/.venv/lib/python3.14/site-packages/django/views/generic/base.py", line 144, in dispatch
return handler(request, *args, **kwargs)
File "/authentik/flows/stage.py", line 153, in post
return self.challenge_valid(challenge)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
File "/authentik/stages/consent/stage.py", line 153, in challenge_valid
consent.save()
~~~~~~~~~~~~^^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/base.py", line 902, in save
self.save_base(
~~~~~~~~~~~~~~^
using=using,
^^^^^^^^^^^^
...<2 lines>...
update_fields=update_fields,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/base.py", line 1008, in save_base
updated = self._save_table(
raw,
...<4 lines>...
update_fields,
)
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/base.py", line 1169, in _save_table
results = self._do_insert(
cls._base_manager, using, fields, returning_fields, raw
)
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/base.py", line 1210, in _do_insert
return manager._insert(
~~~~~~~~~~~~~~~^
[self],
^^^^^^^
...<3 lines>...
raw=raw,
^^^^^^^^
)
^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/manager.py", line 87, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/query.py", line 1873, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/models/sql/compiler.py", line 1882, in execute_sql
cursor.execute(sql, params)
~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/backends/utils.py", line 79, in execute
return self._execute_with_wrappers(
~~~~~~~~~~~~~~~~~~~~~~~~~~~^
sql, params, many=False, executor=self._execute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/backends/utils.py", line 100, in _execute
with self.db.wrap_database_errors:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/ak-root/.venv/lib/python3.14/site-packages/django/db/backends/utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/ak-root/.venv/lib/python3.14/site-packages/django_prometheus/db/common.py", line 69, in execute
return super().execute(*args, **kwargs)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/ak-root/.venv/lib/python3.14/site-packages/psycopg/cursor.py", line 117, in execute
raise ex.with_traceback(None)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "authentik_stages_consent_user_id_application_id_p_e44c6458_uniq"
DETAIL: Key (user_id, application_id, permissions)=(6, a6a4972a-ecd3-4add-98d9-542c96b068a7, email openid profile) already exists.
```
Contributor guide
Research direction
Start at authentik/stages/consent/stage.py around challenge_valid, using the reported IntegrityError and the reproduction flow with an expired explicit-consent token as the entry point. Trace how the existing consent record is handled during login and identify the relevant consent-stage tests; done means the described login flow no longer fails on the unique constraint while preserving valid consent behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, kubernetes, postgresql, python
- Domain
- authentication, databases, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 48/100