Postgresql operations exception are not well handled
Summary
When SQLAlchemy ORM raise exception on database operation, PostgreSQL exception are not well handled
Steps to reproduce
- Add the same email in the "Subscribe" section twice
What is the current bug behavior?
500
error
What is the expected correct behavior?
Should be handled correctly with in app try/except
Relevant logs and/or screenshots
[2022-07-15 09:00:14 +0200] [8] [ERROR] Exception on /notification/suscribe [POST]
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1819, in _execute_context
self.dialect.do_execute(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
cursor.execute(statement, parameters)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "subscriber_email_key"
DETAIL: Key (email)=(xxxx@example.fr) already exists.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/app/ProdManager/helpers/resource.py", line 118, in create_resource
db.session.commit()
File "<string>", line 2, in commit
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1451, in commit
self._transaction.commit(_to_root=self.future)
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 829, in commit
self._prepare_impl()
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 808, in _prepare_impl
self.session.flush()
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 3383, in flush
self._flush(objects)
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 3522, in _flush
with util.safe_reraise():
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
compat.raise_(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
raise exception
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 3483, in _flush
flush_context.execute()
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/unitofwork.py", line 456, in execute
rec.execute(self)
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/unitofwork.py", line 630, in execute
util.preloaded.orm_persistence.save_obj(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/persistence.py", line 245, in save_obj
_emit_insert_statements(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/orm/persistence.py", line 1238, in _emit_insert_statements
result = connection._execute_20(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1631, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 332, in _execute_on_connection
return connection._execute_clauseelement(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1498, in _execute_clauseelement
ret = self._execute_context(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1862, in _execute_context
self._handle_dbapi_exception(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2043, in _handle_dbapi_exception
util.raise_(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/util/compat.py", line 208, in raise_
raise exception
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1819, in _execute_context
self.dialect.do_execute(
File "/usr/local/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "subscriber_email_key"
DETAIL: Key (email)=(xxxx@example.fr) already exists.
[SQL: INSERT INTO subscriber (email) VALUES (%(email)s) RETURNING subscriber.id]
[parameters: {'email': 'xxxx@example.fr'}]
(Background on this error at: https://sqlalche.me/e/14/gkpj)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/app/ProdManager/routes/notification/views.py", line 35, in subscribe
_ = create_resource(Subscriber, dict(
File "/app/ProdManager/helpers/resource.py", line 125, in create_resource
raise ServerError(error) from error
ProdManager.helpers.response.ServerError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "subscriber_email_key"
DETAIL: Key (email)=(xxxx@example.fr) already exists.
[SQL: INSERT INTO subscriber (email) VALUES (%(email)s) RETURNING subscriber.id]
[parameters: {'email': 'xxxx@example.fr'}]
(Background on this error at: https://sqlalche.me/e/14/gkpj)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1523, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1509, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/app/ProdManager/routes/notification/views.py", line 41, in subscribe
return abort(error.code, dict(
File "/usr/local/lib/python3.10/site-packages/werkzeug/exceptions.py", line 879, in abort
_aborter(status, *args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/werkzeug/exceptions.py", line 862, in __call__
raise self.mapping[code](*args, **kwargs)
werkzeug.exceptions.InternalServerError: 500 Internal Server Error: {'message': 'Abonnement aux notifications échoué', 'reasons': {'scope': [IntegrityError('(psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "subscriber_email_key"\nDETAIL: Key (email)=(xxxx@example.fr) already exists.\n')]}}
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 2077, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1525, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1384, in handle_user_exception
return self.handle_http_exception(e)
File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1324, in handle_http_exception
return self.ensure_sync(handler)(e)
File "/app/ProdManager/errors/server.py", line 5, in internal_error
return render_template("error/500.html",
File "/usr/local/lib/python3.10/site-packages/flask/templating.py", line 148, in render_template
return _render(
File "/usr/local/lib/python3.10/site-packages/flask/templating.py", line 128, in _render
rv = template.render(context)
File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
self.environment.handle_exception()
File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
raise rewrite_traceback_stack(source=source)
File "/app/ProdManager/templates/error/500.html", line 3, in top-level template code
{% set error_title = _("error_500") %}
File "/app/ProdManager/templates/error/base.html", line 4, in top-level template code
{% set share_title = _("error_title") %}
File "/app/ProdManager/templates/base.html", line 86, in top-level template code
{% block content %}{% endblock %}
File "/app/ProdManager/templates/error/base.html", line 14, in block 'content'
{{ attribute }} : {{ ",".join(reason) }}
TypeError: sequence item 0: expected str instance, IntegrityError found
Environment info
0.11.0