Uploaded image for project: 'Project Quay'
  1. Project Quay
  2. PROJQUAY-8847

Claiming an org that has already been claimed sometimes leads to a 500

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Cannot Reproduce
    • Icon: Normal Normal
    • None
    • quay-v3.13.0
    • quay
    • False
    • Hide

      None

      Show
      None
    • False
    • Quay Enterprise

      When we claim an org that was already claimed by the same user, Quay sometimes errors out with a duplicate entry exception which causes a 500:

      2025-04-18T20:03:23.350983294Z gunicorn-web stdout | 2025-04-18 20:03:23,350 [294] [ERROR] [gunicorn.error] Error handling request /api/v1/superuser/takeownership/NAMESPACE_NAME
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout | Traceback (most recent call last):
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 3057, in execute_sql
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     cursor.execute(sql, params or ())
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout | psycopg2.errors.InFailedSqlTransaction: current transaction is aborted, commands ignored until end of transaction block
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout | During handling of the above exception, another exception occurred:
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout | Traceback (most recent call last):
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/gunicorn/workers/base_async.py", line 55, in handle
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     self.handle_request(listener_name, req, client, addr)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/gunicorn/workers/ggevent.py", line 128, in handle_request
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     super().handle_request(listener_name, req, sock, addr)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/gunicorn/workers/base_async.py", line 108, in handle_request
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     respiter = self.wsgi(environ, resp.start_response)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/app.py", line 2213, in __call__
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return self.wsgi_app(environ, start_response)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 183, in __call__
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return self.app(environ, start_response)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/app.py", line 2193, in wsgi_app
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     response = self.handle_exception(e)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask_restful/__init__.py", line 298, in error_router
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return original_handler(e)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     response = self.full_dispatch_request()
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     rv = self.handle_user_exception(e)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask_restful/__init__.py", line 298, in error_router
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return original_handler(e)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     rv = self.dispatch_request()
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/endpoints/decorators.py", line 285, in wrapper
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return func(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/auth/decorators.py", line 68, in wrapper
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return func(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/util/request.py", line 64, in wrapper
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return decorator(func)(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask_restful/utils/cors.py", line 35, in wrapped_function
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     resp = make_response(f(*args, **kwargs))
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/endpoints/csrf.py", line 71, in wrapper
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     resp = func(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask_restful/__init__.py", line 489, in wrapper
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     resp = resource(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask/views.py", line 109, in view
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return current_app.ensure_sync(self.dispatch_request)(**kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/flask_restful/__init__.py", line 604, in dispatch_request
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     resp = meth(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/endpoints/decorators.py", line 189, in wrapper
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return func(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/endpoints/api/__init__.py", line 555, in wrapped
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return func(*args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/endpoints/api/superuser.py", line 815, in post
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     log_action("take_ownership", authed_user.username, log_metadata)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/endpoints/api/__init__.py", line 624, in log_action
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     logs_model.log_action(
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/data/logs_model/table_logs_model.py", line 232, in log_action
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     model.log.log_action(
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/data/model/log.py", line 248, in log_action
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     account = User.get(User.username == user_or_organization_name).id
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/data/readreplica.py", line 174, in get
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return sq.get()
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 6741, in get
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return clone.execute(database)[0]
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 1845, in inner
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return method(self, database, *args, **kwargs)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 1916, in execute
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return self._execute(database)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 2087, in _execute
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     cursor = database.execute(self)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 3070, in execute
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     return self.execute_sql(sql, params, commit=commit)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/quay-registry/data/database.py", line 228, in execute_sql
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     cursor = super(RetryOperationalError, self).execute_sql(sql, params, commit)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 3064, in execute_sql
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     self.commit()
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 2831, in __exit__
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     reraise(new_type, new_type(exc_value, *exc_args), traceback)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 183, in reraise
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     raise value.with_traceback(tb)
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |   File "/app/lib/python3.9/site-packages/peewee.py", line 3057, in execute_sql
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout |     cursor.execute(sql, params or ())
      2025-04-18T20:03:23.350983294Z gunicorn-web stdout | peewee.InternalError: current transaction is aborted, commands ignored until end of transaction block
      2025-04-18T20:03:23.351256858Z gunicorn-web stdout | 2025-04-18 20:03:23,350 [294] [INFO] [gunicorn.access]  - - [18/Apr/2025:20:03:23 +0000] "POST /api/v1/superuser/takeownership/NAMESPACE_NAME HTTP/1.0" 500 0 "-" "-"
      

      We see the following in the database:

      2025-04-18 20:03:23.347 GMT [3499429] ERROR:  duplicate key value violates unique constraint "teammember_user_id_team_id"
      2025-04-18 20:03:23.347 GMT [3499429] DETAIL:  Key (user_id, team_id)=(1230, 529) already exists.
      2025-04-18 20:03:23.347 GMT [3499429] STATEMENT:  INSERT INTO "teammember" ("user_id", "team_id") VALUES (1230, 529) RETURNING "teammember"."id"
      

      So the user is already member of the owners team in that namespace. Most likely this just needs a try/except block and that should be it. UI should not error out with a 500 on this issue.

      Please check.

              Unassigned Unassigned
              rhn-support-ibazulic Ivan Bazulic
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: