Skip to content

Deleting a user who has updated their own profile fails with CircularDependencyError #44865

Description

@VirtualDylan

Bug description

A user who has updated their own profile through PUT /api/v1/me/ (name or password) can no longer be deleted. The delete fails until some other user edits them.

To reproduce (clean 6.1.0, Postgres metadata database, default config):

  1. As an admin, create a user with any role (Gamma is enough).
  2. Log in as that user and change the first name: PUT /api/v1/me/ with {"first_name": "Changed"}. It answers 200.
  3. As the admin, delete the user from Settings → List Users, or DELETE /api/v1/security/users/<id>.

Expected: the user is deleted.

Actual: the API answers 422:

{"message": "Database exception occurred: Circular dependency detected. (DeleteState(<User at 0x...>))"}

The user list shows only "There was an issue deleting ". The server log has sqlalchemy.exc.CircularDependencyError.

The same happens to an admin who edits their own row with PUT /api/v1/security/users/<own id>. A user who has logged in but never edited themselves deletes fine.

Workaround: have an admin make any edit to the user (deactivating them, for example), then delete. The delete then answers 200.

Cause, as far as I can tell:

  • CurrentUserRestApi.pre_update (superset/views/users/api.py) sets item.changed_by_fk = g.user.id, so after a self-edit the row's changed_by_fk is its own id. The PUT on /api/v1/me/ arrived in 6.0.0 (feat(UserInfo): Migrate User Info FAB to React #33620).
  • Flask-AppBuilder's User model (flask_appbuilder/security/sqla/models.py) declares created_by and changed_by as self-referential relationships without post_update=True. SQLAlchemy's unit of work cannot order the delete of a row whose foreign key points at itself, and raises CircularDependencyError.
  • An admin edit cures it because FAB's UserApi.pre_update moves changed_by_fk to the admin.

4.1.1 does not show it for self-service: resetting your own password there never writes changed_by_fk.

Possible fixes: leave changed_by_fk alone (or null it) when a user edits themselves, null a self-referencing changed_by_fk in SupersetUserApi.pre_delete, or add post_update=True to the two relationships in Flask-AppBuilder.

Screenshots/recordings

No response

Superset version

6.1.0

Python version

3.11

Node version

Not applicable

Browser

Chrome

Additional context

  • Image: apache/superset:6.1.0-py311, plus psycopg2-binary. Flask-AppBuilder 5.0.2, SQLAlchemy 1.4.54, Postgres 16 metadata database.
  • The User relationships are the same on Flask-AppBuilder master, and master here still has the changed_by_fk = g.user.id line, so I expect it reproduces there too. I have not run master.
  • I searched this repo and Flask-AppBuilder for "Circular dependency detected", CircularDependencyError and changed_by_fk and found no existing report. A 2022 comment on cannot delete user "Associated data exists, please delete them first" #13345 mentions the same exception without a cause.

Checklist

  • I have searched Superset docs and Slack and didn't find a solution to my problem.
  • I have searched the GitHub issue tracker and didn't find a similar bug report.
  • I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Activity

  1. dosubot commented on Oct 1, 2026

    @dosubot

    Hi @VirtualDylan! I'm Dosu and I'm helping the Apache Superset team.

    Your diagnosis checks out against current master. CurrentUserRestApi.pre_update sets item.changed_by_fk = g.user.id on every self-edit through PUT /api/v1/me/ and never checks whether the editor is the same row [1].

    Superset already works around FK issues on user deletion. SupersetUserApi overrides FAB's pre_delete to clear item.roles = [] before the delete, because otherwise the role association would block it [2]. That override has no handling for changed_by_fk/created_by_fk, so a self-referencing row still trips SQLAlchemy's circular dependency check on delete. Nulling a self-referencing changed_by_fk/created_by_fk there would follow the same pattern without touching Flask-AppBuilder.

    I didn't find any existing issue, PR, or prior conversation that addresses this.

    To reply, just mention @dosu.


    Docs are dead. Just use Dosu.

    Leave Feedback Ask Dosu about superset Share Dosu with your team

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions